Creative Lab — Keycap API

Förvandla ett källfoto till en fullfärgad, anpassad mekanisk tangentbordskeycap i två steg: prototype genererar en design-rendering av en "färdig keycap" utifrån ditt källfoto. När du har bekräftat den renderingen omvandlar build den till en texturerad 3D-keycapmodell i en enda körning — generering av vitmodell, automatisk placering och kapning i en kalibrerad standardpose, färgsättning av hela modellen och slutlig sammansättning sker allt inom en enda byggtask. De två stegen kopplas samman via input_task_id plus candidate_id.

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

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

Skapa en Keycap Prototype-uppgift

Genererar en färdig renderad keycap-design utifrån källfotot. Uppgiftens resultat innehåller en image_urls-array (den visade renderingen av den färdiga keycapen) och en parallell candidate_ids-array; båda innehåller en enda post. Anropa detta endpoint igen för att få en ny rendering om resultatet inte blev som du ville — varje anrop debiteras separat. Skicka candidate_id tillsammans med prototypuppgiftens ID till build-endpointen. Se The Keycap Prototype Task Object för svarets format.

Parametrar

  • Name
    image_url
    Type
    string
    Obligatorisk
    Description

    Källfoto som Meshy ska omvandla till keycap-designbilder. Vi stöder för närvarande formaten .jpg, .jpeg, .png och .webp.

    Formatet identifieras genom att avkoda bilddatan, inte utifrån URL:ens filändelse — en URL utan filändelse, eller en som omdirigerar, fungerar så länge byte-datan går att avkoda till ett format som stöds. HTTP-omdirigeringar följs. EXIF-orientering normaliseras, så ett roterat mobilfoto används på det sätt det ser ut.

    Begränsningar: minst 32 pixlar på varje sida, högst 178 956 970 pixlar totalt, och högst 20 000 000 byte efter nedladdning. För en Data URI gäller gränsen de avkodade byten, så själva källfilen kan vara upp till den storleken — det är base64-texten som är cirka en tredjedel större, vilket har betydelse för din request-body, inte för denna gräns. En Data URI måste ange en image/*-innehållstyp och ;base64.

    Det finns två sätt att ange bilden på:

    • Publikt tillgänglig URL: En URL som är tillgänglig från det publika internet.
    • Data URI: En base64-kodad data-URI för bilden. Exempel på en Data URI: data:image/jpeg;base64,<din base64-kodade bilddata>.
  • Name
    name
    Type
    string
    Description

    Valfritt uppgiftsnamn för visningsändamål. Maximalt 100 tecken.

  • Name
    remove_background
    Type
    boolean
    standard false
    Description

    När detta sätts till true är den visade renderingen som returneras i image_urls en transparent RGBA PNG med bakgrunden borttagen, så att du kan sätta ihop den med valfri bakgrund.

    Detta gäller endast den visade renderingen. Kandidaten som build-endpointen använder påverkas inte, så 3D-resultatet blir identiskt oavsett.

Returnerar

Svarets result-egenskap innehåller uppgifts-id:t för den nyligen skapade keycap-prototypuppgiften. Fråga Get a Task-endpointen eller prenumerera på streamen tills uppgiften når SUCCEEDED, och hämta sedan posten från candidate_ids och skicka den, tillsammans med uppgifts-ID:t, till build-endpointen.

Felscenarier

  • Name
    400 - Bad Request
    Description

    Begäran kunde inte accepteras. Vanliga orsaker:

    • Saknad parameter: image_url krävs.
    • Ogiltigt bildformat: Den angivna image_url har inte ett format som stöds (.jpg, .jpeg, .png, .webp).
    • Bilddimensioner utanför tillåtet intervall: Bilden är för liten, överskrider den maximala filstorleken, eller överskrider det maximala antalet pixlar.
    • Onåbar URL: image_url kunde inte hämtas (404 eller timeout).
    • Ogiltig Data URI: Base64-strängen är felaktigt formaterad.
    • Innehåll flaggat: Den angivna bilden flaggades av NSFW-moderation.
  • Name
    401 - Unauthorized
    Description

    Autentiseringen misslyckades. Kontrollera din API-nyckel.

  • Name
    402 - Payment Required
    Description

    Kontot använder den kostnadsfria planen (en betald plan krävs för att skapa uppgifter) eller har otillräckligt med credits.

  • Name
    403 - Forbidden
    Description

    Den angivna bilden flaggades av moderation för immateriella rättigheter.

  • Name
    429 - Too Many Requests
    Description

    Du har överskridit din hastighetsgräns.

  • Name
    500 - Internal Server Error
    Description

    Ett oväntat serverfel inträffade — till exempel att innehållsmodereringstjänsten var otillgänglig, att förberedelsen (staging) av den angivna bilden misslyckades, eller att uppgiften inte kunde skapas. I detta fall skapas ingen uppgift, så det är säkert att försöka igen.

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

Skapa en Keycap Build-uppgift

Generera den slutliga texturerade 3D-keycap-modellen från en lyckad prototyp-uppgift och en av dess kandidater. En enda build-uppgift kör hela pipelinen från start till slut — generering av vitmodell från den valda designen, automatisk placering och skärning på keycap-basen med hjälp av en kalibrerad standardpose (ingen interaktiv justering behövs), färgläggning av hela modellen samt slutlig sammansättning och export. En build tar vanligtvis 3–7 minuter, mot den övre gränsen när flera builds körs samtidigt. Se The Keycap Build Task Object för svarets format.

Parametrar

  • Name
    input_task_id
    Type
    string
    Obligatorisk
    Description

    Uppgifts-ID för en prototyp-uppgift som skapats via samma OpenAPI-endpoint. Prototypen måste ha skapats av samma Meshy-konto, måste ha nått SUCCEEDED och måste ha genererat minst en kandidat.

    Prototyp-uppgifter skapade via webbappen accepteras inte — build-endpointen accepterar endast prototyp-uppgifter som skapats via POST /openapi/creative-lab/keycap/v1/prototype och avvisar alla andra källor med 404.

  • Name
    candidate_id
    Type
    string
    Obligatorisk
    Description

    Kandidaten som ska byggas, hämtad från candidate_ids-arrayen i den lyckade prototyp-uppgiften. Måste tillhöra den uppgiften; alla andra värden avvisas med 400.

  • Name
    name
    Type
    string
    Description

    Valfritt uppgiftsnamn för visningsändamål. Maximalt 100 tecken.

options

Valfri geometrijustering. Varje fält har ett kalibrerat standardvärde — skicka endast de du vill åsidosätta.

  • Name
    base_model
    Type
    string
    standard cherry-mx-1x1-r1
    Description

    Keycap-basen att bygga på. För närvarande är det enda tillgängliga värdet cherry-mx-1x1-r1 — en standard Cherry MX-profil 1u keycap. 3–5 ytterligare vanliga standardstorlekar är planerade; anpassade storlekar stöds inte.

  • Name
    head_size_mm
    Type
    number
    standard 23
    Description

    Målstorlek för det skulpterade huvudet, i millimeter: dess längsta dimension skalas till detta värde. Intervall: [10, 40]. Värden över ungefär 32.9 kan reduceras så att huvudet fortfarande får plats inom basens skyddande fotavtrycksgräns, så den levererade längsta dimensionen kan bli mindre än begärt. Det tillämpade värdet återges inte i uppgiftsobjektet idag — om du behöver bekräfta storleken du faktiskt fick, mät begränsningsrutan för keycap-head-nätet i den nedladdade modellen.

  • Name
    vertical_offset_mm
    Type
    number
    standard 0
    Description

    Vertikal förskjutning som appliceras på huvudet innan det placeras på basen, i millimeter. Intervall: [-5, 5].

Returer

Egenskapen result i svaret innehåller uppgifts-id för den nyskapade keycap build-uppgiften. Fråga Get a Task-endpointen eller prenumerera på stream tills uppgiften når SUCCEEDED, ladda sedan ner artefakterna från model_urls.glb och model_urls.obj_zip.

Felläge

  • Name
    400 - Bad Request
    Description

    Förfrågan var oacceptabel. Vanliga orsaker:

    • Saknad parameter: input_task_id och candidate_id krävs.
    • Ogiltig UUID: input_task_id är inte en giltig UUID.
    • Överordnad ej lyckad: Den refererade prototyp-uppgiften har ännu inte nått SUCCEEDED.
    • Inga kandidater: Prototyp-uppgiften lyckades men genererade inga kandidater.
    • Okänd kandidat: candidate_id är inte en av inmatningsuppgiftens kandidater.
    • Alternativ utanför intervall: Ett av fälten i options låg utanför sitt tillåtna intervall eller enum-uppsättning.
  • Name
    401 - Unauthorized
    Description

    Autentiseringen misslyckades. Kontrollera din API-nyckel.

  • Name
    402 - Payment Required
    Description

    Kontot har den kostnadsfria planen (en betald plan krävs för att skapa uppgifter) eller har otillräckliga credits.

  • Name
    404 - Not Found
    Description

    Den refererade prototyp-uppgiften finns inte, tillhör en annan användare, eller skapades via webbappen (endast prototyp-uppgifter i API-mode kan kedjas till build).

  • Name
    429 - Too Many Requests
    Description

    Du har överskridit din hastighetsgräns.

  • Name
    500 - Internal Server Error
    Description

    Ett oväntat serverfel inträffade — till exempel var innehållsmoderationstjänsten otillgänglig, det gick inte att förbereda indatabilden, eller uppgiften kunde inte skapas. Ingen uppgift skapas i detta fall, så det är säkert att försöka igen.

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

Hämta en Keycap-uppgift

Hämta en prototyp- eller byggnadsuppgift givet ett giltigt uppgifts-id. URL-sökvägen måste matcha uppgiftens skede — en byggnadsuppgift som hämtas via /prototype/:id returnerar 404, och vice versa.

Se The Keycap Prototype Task Object och The Keycap Build Task Object för svarens format.

Parametrar

  • Name
    id
    Type
    path
    Description

    Unik identifierare för keycap-uppgiften som ska hämtas.

Returnerar

Svaret innehåller keycap-uppgiftsobjektet. Formatet beror på vilket skede som begärdes.

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

Radera en Keycap-uppgift

Avbryt en keycap-uppgift. Om uppgiften fortfarande är PENDING återbetalas de credits som förbrukades vid skapandet. Uppgifter som redan är IN_PROGRESS avbryts utan återbetalning (arbetaren kan redan hålla på att förbruka resurser). Uppgifter som redan har nått ett slutgiltigt tillstånd (SUCCEEDED, FAILED, CANCELED) kan inte avbrytas.

URL-sökvägen måste matcha uppgiftens steg — DELETE/prototype/:buildId returnerar 404.

Sökvägsparametrar

  • Name
    id
    Type
    path
    Description

    Unik identifierare för keycap-uppgiften som ska avbrytas.

Returnerar

Returnerar 204 No Content vid lyckat anrop med en tom body.

Felläge

  • Name
    400 - Bad Request
    Description

    Uppgiften är redan i ett slutgiltigt tillstånd och kan inte avbrytas.

  • Name
    404 - Not Found
    Description

    Uppgiften finns inte, tillhör en annan användare, eller dess steg matchar inte URL-sökvägen.

  • Name
    500 - Internal Server Error
    Description

    Ett oväntat serverfel uppstod vid avbrytning. Uppgiften kan eller kan inte ha blivit avbruten — läs den igen för att bekräfta innan du försöker igen.

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

Streama en Keycap-uppgift

Streama realtidsuppdateringar för en keycap-uppgift via Server-Sent Events (SSE). URL-sökvägen måste matcha uppgiftens fas — att öppna en ström vid /prototype/:buildId/stream skickar en enda event: error-payload med status_code: 404 och stänger sedan strömmen.

Parametrar

  • Name
    id
    Type
    path
    Description

    Unik identifierare för den keycap-uppgift som ska strömmas.

Returnerar

Returnerar en ström av Keycap Prototype- eller Keycap Build-uppgiftsobjekt som Server-Sent Events. Varje bildruta innehåller hela uppgiftsobjektet för fasen — samma form som Get-endpointen returnerar — så medan uppgiften är PENDING eller IN_PROGRESS är utdatafälten helt enkelt inte ifyllda ännu (null, [] eller {}) och finished_at är 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)

Lista Keycap-uppgifter

Hämta en sidindelad lista över dina keycap-uppgifter för ett enskilt steg. URL-sökvägen väljer steget — /prototype returnerar prototypuppgifter; /build returnerar byggnadsuppgifter. Uppgifter från det andra steget ingår inte i något av svaren.

Sökvägsparametrar

  • Name
    stage
    Type
    path
    Obligatorisk
    Description

    Antingen prototype eller build. Samlingen returnerar endast uppgifter vars steg matchar URL:en — att hämta /prototype returnerar aldrig byggnadsuppgifter och vice versa.

Frågeparametrar

  • Name
    page_num
    Type
    integer
    standard 1
    Description

    Sidnummer för paginering.

  • Name
    page_size
    Type
    integer
    standard 10
    Description

    Gräns för sidstorlek. Maximalt tillåtet är 100 objekt.

  • Name
    sort_by
    Type
    string
    standard -created_at
    Description

    Fält att sortera efter. Tillgängliga värden:

    • +created_at: Sortera efter skapandetid i stigande ordning.
    • -created_at: Sortera efter skapandetid i fallande ordning.

Returnerar

Returnerar en sidindelad lista över objektet för uppgifter per steg — antingen keycap-prototypuppgiftsobjektet vid listning av /prototype eller keycap-byggnadsuppgiftsobjektet vid listning av /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"
    ]
  }
]

Objektet Keycap Prototype Task

Objektet Keycap Prototype Task är en arbetsenhet som Meshy håller reda på för att generera en bild av den färdiga keycap-designen från ett källfoto. Resultatet av detta steg kopplas vidare till byggsteget via input_task_id plus candidate_id.

Egenskaper

  • Name
    id
    Type
    string
    Description

    Unik identifierare för uppgiften. Även om vi använder en k-sorterbar UUID för uppgiftsid:n som implementationsdetalj, bör du inte göra några antaganden om formatet på id:t.

  • Name
    type
    Type
    string
    Description

    Uppgiftens typ. Värdet är creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    Uppgiftens namn som angavs när uppgiften skapades. Tom sträng om inget namn angavs.

  • Name
    status
    Type
    string
    Description

    Uppgiftens status. Möjliga värden är ett av PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Uppgiftens progress. Om uppgiften ännu inte har startat är denna egenskap 0. När uppgiften har lyckats blir den 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Tidsstämpel för när uppgiften skapades, i millisekunder.

  • Name
    started_at
    Type
    timestamp
    Description

    Tidsstämpel för när uppgiften startades, i millisekunder. Om uppgiften ännu inte har startat är denna egenskap 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Tidsstämpel för när uppgiften avslutades, i millisekunder. Om uppgiften ännu inte är avslutad är denna egenskap 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Tidsstämpel för när uppgiftens resultat upphör att gälla, i millisekunder.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Antalet föregående uppgifter.

  • Name
    task_error
    Type
    object
    Description

    Felinformation för misslyckade uppgifter. Se Fel för den fullständiga referensen för objektet task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Antalet credits som förbrukats av denna uppgift. En uppgift som når SUCCEEDED debiteras hela beloppet för sitt steg. En uppgift som aldrig skapas (ett 4xx-fel vid förfrågningstillfället, inklusive ett moderation-avslag) debiteras inte alls. En uppgift som når FAILED returnerar 0 — avgiften återbetalas, inklusive en asynkron moderation-blockering. Att avbryta via DELETE återbetalar endast medan uppgiften fortfarande är PENDING; en uppgift som redan är IN_PROGRESS förblir debiterad, eftersom arbetet redan har utförts.

  • Name
    image_urls
    Type
    array of strings
    Description

    Nedladdningsbar URL för renderingen av den färdiga keycap-designen — hur kandidaten ser ut som färdig keycap. Innehåller en enda post; image_urls[i] motsvarar candidate_ids[i]. Tom tills uppgiften når SUCCEEDED. URL:en är endast för visning; build-endpointen använder candidate_ids, inte dessa URL:er. Samma URL-livscykel som model_urls: signerad, ingen Authorization-header, giltig till expires_at, och stabil när uppgiften läses om.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Opaka kandidatidentifierare, parallella med image_urls. Skicka posten som motsvarar din valda design som candidate_id i build-förfrågan. Gör inte några antaganden om formatet på dessa id:n.

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

The Keycap Build Task Object

Keycap Build Task-objektet är en arbetsenhet som Meshy håller reda på för att generera den slutliga texturerade 3D-keycappen från en lyckad prototyptask och en vald kandidat. En enskild build körs genom hela pipelinen — vitmodellsgenerering, automatisk placering och kapning, färgsättning, sammansättning och export.

Egenskaper

  • Name
    id
    Type
    string
    Description

    Unik identifierare för tasken.

  • Name
    type
    Type
    string
    Description

    Taskens typ. Värdet är creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    Tasknamnet som angavs när tasken skapades. Tom sträng om inget namn angavs.

  • Name
    status
    Type
    string
    Description

    Taskens status. Möjliga värden är ett av PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Taskens progress. Om tasken ännu inte har startats är denna egenskap 0. När tasken har lyckats blir den 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Tidsstämpel för när tasken skapades, i millisekunder.

  • Name
    started_at
    Type
    timestamp
    Description

    Tidsstämpel för när tasken startades, i millisekunder.

  • Name
    finished_at
    Type
    timestamp
    Description

    Tidsstämpel för när tasken avslutades, i millisekunder.

  • Name
    expires_at
    Type
    timestamp
    Description

    Tidsstämpel för när taskens resultat upphör att gälla, i millisekunder.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Antalet föregående tasks. Är endast meningsfullt när status är PENDING.

  • Name
    task_error
    Type
    object
    Description

    Felinformation för misslyckade tasks. Se Fel för den fullständiga referensen för task_error-objektet.

  • Name
    consumed_credits
    Type
    integer
    Description

    Antalet credits som förbrukats av denna task. En task som når SUCCEEDED debiteras hela beloppet för sitt steg. En task som aldrig skapas (ett 4xx-fel vid begäranstillfället, inklusive en moderation-avvisning) debiteras inte alls. En task som når FAILED returnerar 0 — avgiften återbetalas, inklusive vid en asynkron moderation-blockering. Att avbryta via DELETE återbetalar endast medan tasken fortfarande är PENDING; en task som redan är IN_PROGRESS förblir debiterad, eftersom arbetet redan har utförts.

  • Name
    model_urls
    Type
    object
    Description

    Nedladdningsbara URL:er för de genererade modellfilerna. Både GLB- och OBJ-paketet exporteras i verklig skala i millimeter, Y-upp, med framsidan av keycappen riktad mot +Z. Näten heter keycap-head och keycap-base; när basen faller tillbaka på en mönsterfyllning finns även ett tredje nät, keycap-base-interior, för stamhålan. Utgå inte från att det alltid finns exakt två nät.

    Dessa är signerade URL:er: hämta dem utan en Authorization-header. De förblir giltiga tills expires_at, som är 3 dagar efter finished_at, och om tasken läses igen inom det fönstret returneras samma URL istället för en nysignerad. Ladda ner och spara filerna själv innan det inträffar — det finns inget sätt att uppdatera en utgången länk.

    • Name
      glb
      Type
      string
      Description

      Nedladdningsbar URL till den slutliga texturerade model.glb.

    • Name
      obj_zip
      Type
      string
      Description

      Nedladdningsbar URL till ett zip-paket som innehåller model.obj, model.mtl och de texturer i PNG-format som dess MTL faktiskt refererar till. En bas med enfärgad yta levereras endast med keycap-head.png; en bas med mönster levereras även med keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    Nedladdningsbara URL:er för mellanliggande processbilder, nyckelbaserade efter typ. Samma URL-livscykel som model_urls: signerad, ingen Authorization-header, giltig tills expires_at, och stabil när tasken läses igen. Typer som för närvarande genereras:

    • head_design — designbilden för den valda kandidaten som build-processen använde (finns alltid).
    • composite — den färdiga keycap-visningsrendreringen av den valda kandidaten (finns när tillgänglig).
    • base_canvas — den målade keycap-bas-canvasen (finns när tillgänglig).

    Betrakta nyckelsetet som öppet för utökning; nya typer kan läggas till utan att det innebär en brytande ändring.

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

End-to-End Example

Det fullständiga flödet: skapa en prototyp från ett foto, pollra den till SUCCEEDED, välj en kandidat från candidate_ids, skapa en build med den kandidaten, pollra builden till SUCCEEDED, och ladda sedan ner GLB- och OBJ-paketet från model_urls.

Exemplet väljer den första kandidaten programmatiskt. I en verklig integration skulle du visa posten image_urls för slutanvändaren och låta dem välja; det valda indexet mappar 1:1 mot 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"