Creative Lab — Keycap API

Trasforma una foto sorgente in un tasto (keycap) per tastiera meccanica personalizzato e a colori pieni in due fasi: prototype genera il render di design di un "tasto finito" a partire dalla foto in input. Una volta confermato tale render, build lo trasforma in un modello 3D di keycap texturizzato in un'unica esecuzione — generazione del modello bianco, alloggiamento e taglio automatici su una posa predefinita calibrata, colorazione dell'intero modello e assemblaggio finale avvengono tutti all'interno di un'unica attività di build. Le due fasi sono collegate tramite input_task_id e candidate_id.

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

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

Crea un'attività di prototipo Keycap

Genera un render del design di un keycap finito a partire dalla foto sorgente. Il risultato dell'attività contiene un array image_urls (il render di visualizzazione del keycap finito) e un array parallelo candidate_ids; entrambi contengono una singola voce. Richiama nuovamente questo endpoint per ottenere un altro render se il risultato non è quello desiderato — ogni chiamata viene fatturata separatamente. Passa il candidate_id insieme all'ID dell'attività di prototipo all'endpoint di build. Fai riferimento a The Keycap Prototype Task Object per la struttura della risposta.

Parametri

  • Name
    image_url
    Type
    string
    Obbligatorio
    Description

    Foto sorgente che Meshy trasformerà in immagini di design del keycap. Attualmente supportiamo i formati .jpg, .jpeg, .png e .webp.

    Il formato viene rilevato decodificando i dati dell'immagine, non dall'estensione del file nell'URL — un URL senza estensione, o che effettua un reindirizzamento, funziona purché i byte vengano decodificati in un formato supportato. I reindirizzamenti HTTP vengono seguiti. L'orientamento EXIF viene normalizzato, quindi una foto scattata da telefono e ruotata viene utilizzata come appare visivamente.

    Limiti: almeno 32 pixel per lato, al massimo 178.956.970 pixel in totale e al massimo 20.000.000 byte una volta scaricata. Per una Data URI il limite si applica ai byte decodificati, quindi il file sorgente stesso può arrivare a quella dimensione — è il testo base64 a essere circa un terzo più grande, il che è rilevante per il corpo della richiesta, non per questo limite. Una Data URI deve dichiarare un content type image/* e ;base64.

    Ci sono due modi per fornire l'immagine:

    • URL pubblicamente accessibile: un URL accessibile dalla rete internet pubblica.
    • Data URI: una data URI dell'immagine codificata in base64. Esempio di data URI: data:image/jpeg;base64,<i tuoi dati immagine codificati in base64>.
  • Name
    name
    Type
    string
    Description

    Nome opzionale dell'attività a scopo di visualizzazione. Massimo 100 caratteri.

  • Name
    remove_background
    Type
    boolean
    predefinito false
    Description

    Quando impostato su true, il render di visualizzazione restituito in image_urls è un PNG RGBA trasparente con lo sfondo rimosso, in modo da poterlo comporre su qualsiasi sfondo.

    Questo si applica solo al render di visualizzazione. Il candidato consumato dall'endpoint di build non è influenzato, quindi il risultato 3D è identico in entrambi i casi.

Valori restituiti

La proprietà result della risposta contiene l'id dell'attività appena creata per il prototipo del keycap. Effettua il polling dell'endpoint Get a Task oppure sottoscrivi lo stream finché l'attività non raggiunge lo stato SUCCEEDED, quindi prendi la voce da candidate_ids e passala, insieme all'ID dell'attività, all'endpoint di build.

Modalità di errore

  • Name
    400 - Bad Request
    Description

    La richiesta non era accettabile. Cause comuni:

    • Parametro mancante: image_url è obbligatorio.
    • Formato immagine non valido: l'image_url fornito non è in un formato supportato (.jpg, .jpeg, .png, .webp).
    • Dimensioni dell'immagine fuori intervallo: l'immagine è troppo piccola, supera la dimensione massima del file o supera il numero massimo di pixel.
    • URL non raggiungibile: non è stato possibile scaricare l'image_url (404 o timeout).
    • Data URI non valida: la stringa base64 è malformata.
    • Contenuto segnalato: l'immagine in ingresso è stata segnalata dalla moderation NSFW.
  • Name
    401 - Unauthorized
    Description

    Autenticazione non riuscita. Controlla la tua chiave API.

  • Name
    402 - Payment Required
    Description

    L'account è su un piano gratuito (è richiesto un piano a pagamento per creare attività) oppure ha crediti insufficienti.

  • Name
    403 - Forbidden
    Description

    L'immagine in ingresso è stata segnalata dalla moderation sulla proprietà intellettuale.

  • Name
    429 - Too Many Requests
    Description

    Hai superato il tuo limite di frequenza.

  • Name
    500 - Internal Server Error
    Description

    Si è verificato un errore lato server imprevisto — ad esempio il servizio di content moderation non era disponibile, la fase di staging dell'immagine in ingresso non è riuscita, oppure non è stato possibile creare l'attività. In questo caso non viene creata alcuna attività, quindi è sicuro riprovare.

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

Creazione di un'attività di build del Keycap

Genera il modello 3D del keycap testurizzato finale a partire da un'attività di prototipo riuscita e da uno dei suoi candidati. Una singola attività di build esegue l'intera pipeline end to end — generazione del modello bianco a partire dal design scelto, posizionamento e taglio automatici sulla base del keycap utilizzando una posa predefinita calibrata (nessuna regolazione interattiva necessaria), colorazione dell'intero modello e assemblaggio ed esportazione finali. Una build richiede tipicamente 3–7 minuti, avvicinandosi al limite superiore quando più build vengono eseguite contemporaneamente. Fai riferimento a L'oggetto attività di build del Keycap per la struttura della risposta.

Parametri

  • Name
    input_task_id
    Type
    string
    Obbligatorio
    Description

    L'ID dell'attività di un'attività di prototipo creata tramite questo stesso endpoint OpenAPI. Il prototipo deve essere stato creato dallo stesso account Meshy, deve aver raggiunto lo stato SUCCEEDED e deve aver prodotto almeno un candidato.

    Le attività di prototipo create tramite la webapp non sono accettate — l'endpoint di build accetta solo attività di prototipo prodotte da POST /openapi/creative-lab/keycap/v1/prototype e rifiuta qualsiasi altra origine con 404.

  • Name
    candidate_id
    Type
    string
    Obbligatorio
    Description

    Il candidato da costruire, prelevato dall'array candidate_ids dell'attività di prototipo riuscita. Deve appartenere a quell'attività; qualsiasi altro valore viene rifiutato con 400.

  • Name
    name
    Type
    string
    Description

    Nome facoltativo dell'attività per scopi di visualizzazione. Massimo 100 caratteri.

options

Regolazione facoltativa della geometria. Ogni campo ha un valore predefinito calibrato — invia solo quelli che desideri sovrascrivere.

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

    La base del keycap su cui costruire. Attualmente l'unico valore disponibile è cherry-mx-1x1-r1 — un keycap standard 1u con profilo Cherry MX. Sono previste 3–5 dimensioni standard mainstream aggiuntive; le dimensioni personalizzate non sono supportate.

  • Name
    head_size_mm
    Type
    number
    predefinito 23
    Description

    Dimensione target della testa scolpita, in millimetri: la sua dimensione più lunga viene scalata a questo valore. Intervallo: [10, 40]. Valori superiori a circa 32.9 possono essere ridotti affinché la testa rientri comunque nel limite di ingombro protettivo della base, quindi la dimensione più lunga fornita può essere inferiore a quella richiesta. Il valore applicato non viene attualmente restituito nell'oggetto attività — se hai bisogno di confermare la dimensione effettivamente ricevuta, misura la bounding box della mesh keycap-head nel modello scaricato.

  • Name
    vertical_offset_mm
    Type
    number
    predefinito 0
    Description

    Offset verticale applicato alla testa prima che venga posizionata sulla base, in millimetri. Intervallo: [-5, 5].

Valori restituiti

La proprietà result della risposta contiene l'id dell'attività appena creata per la build del keycap. Effettua il polling dell'endpoint Recupera un'attività oppure sottoscrivi lo stream finché l'attività non raggiunge lo stato SUCCEEDED, quindi scarica gli artefatti da model_urls.glb e model_urls.obj_zip.

Modalità di errore

  • Name
    400 - Bad Request
    Description

    La richiesta non era accettabile. Cause comuni:

    • Parametro mancante: input_task_id e candidate_id sono obbligatori.
    • UUID non valido: input_task_id non è un UUID valido.
    • Attività padre non riuscita: l'attività di prototipo referenziata non ha ancora raggiunto lo stato SUCCEEDED.
    • Nessun candidato: l'attività di prototipo è riuscita ma non ha prodotto candidati.
    • Candidato sconosciuto: candidate_id non corrisponde a nessuno dei candidati dell'attività di input.
    • Opzioni fuori intervallo: uno dei campi di options non rientrava nell'intervallo consentito o nell'insieme di valori enum.
  • Name
    401 - Unauthorized
    Description

    Autenticazione non riuscita. Controlla la tua chiave API.

  • Name
    402 - Payment Required
    Description

    L'account è su un piano gratuito (è richiesto un piano a pagamento per creare attività) oppure ha crediti insufficienti.

  • Name
    404 - Not Found
    Description

    L'attività di prototipo referenziata non esiste, appartiene a un altro utente oppure è stata creata tramite la webapp (solo le attività di prototipo in modalità API possono essere incatenate a una build).

  • Name
    429 - Too Many Requests
    Description

    Hai superato il tuo limite di frequenza.

  • Name
    500 - Internal Server Error
    Description

    Si è verificato un errore imprevisto lato server — ad esempio il servizio di moderation dei contenuti non era disponibile, il caricamento dell'immagine di input non è riuscito, oppure non è stato possibile creare l'attività. In questo caso non viene creata alcuna attività, quindi è sicuro riprovare.

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

Recuperare un'attività Keycap

Recupera un'attività di prototipo o build dato un id di attività valido. Il percorso URL deve corrispondere alla fase dell'attività — un'attività di build recuperata tramite /prototype/:id restituisce 404, e viceversa.

Fai riferimento a L'oggetto attività di prototipo Keycap e L'oggetto attività di build Keycap per le forme delle risposte.

Parametri

  • Name
    id
    Type
    path
    Description

    Identificatore univoco dell'attività keycap da recuperare.

Restituisce

La risposta contiene l'oggetto attività keycap. La forma dipende da quale fase è stata richiesta.

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

Elimina un'attività Keycap

Annulla un'attività keycap. Se l'attività è ancora PENDING, i crediti consumati al momento della creazione vengono rimborsati. Le attività già IN_PROGRESS vengono annullate senza rimborso (il worker potrebbe già star consumando risorse). Le attività che hanno già raggiunto uno stato terminale (SUCCEEDED, FAILED, CANCELED) non possono essere annullate.

Il percorso dell'URL deve corrispondere alla fase dell'attività — DELETE su /prototype/:buildId restituisce 404.

Parametri del percorso

  • Name
    id
    Type
    path
    Description

    Identificatore univoco dell'attività keycap da annullare.

Restituisce

Restituisce 204 No Content in caso di successo con un corpo vuoto.

Modalità di errore

  • Name
    400 - Bad Request
    Description

    L'attività si trova già in uno stato terminale e non può essere annullata.

  • Name
    404 - Not Found
    Description

    L'attività non esiste, appartiene a un altro utente, oppure la sua fase non corrisponde al percorso dell'URL.

  • Name
    500 - Internal Server Error
    Description

    Si è verificato un errore imprevisto lato server durante l'annullamento. L'attività potrebbe essere stata annullata oppure no: rileggila per confermare prima di riprovare.

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

Stream di un'attività Keycap

Trasmetti in streaming aggiornamenti in tempo reale per un'attività keycap tramite Server-Sent Events (SSE). Il percorso dell'URL deve corrispondere alla fase dell'attività — aprire uno stream su /prototype/:buildId/stream emette un singolo event: error payload con status_code: 404 e chiude lo stream.

Parametri

  • Name
    id
    Type
    path
    Description

    Identificatore univoco dell'attività keycap da trasmettere in streaming.

Valori restituiti

Restituisce uno stream di oggetti attività Keycap Prototype o Keycap Build come Server-Sent Events. Ogni frame trasporta l'oggetto attività completo per la fase — la stessa struttura restituita dall'endpoint Get — quindi mentre l'attività è PENDING o IN_PROGRESS i campi di output semplicemente non sono ancora popolati (null, [] o {}) e 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)

Elenco delle attività Keycap

Recupera un elenco paginato delle tue attività keycap per una singola fase. Il percorso URL seleziona la fase — /prototype restituisce le attività di prototipo; /build restituisce le attività di build. Le attività dell'altra fase non sono incluse in nessuna delle due risposte.

Parametri del percorso

  • Name
    stage
    Type
    path
    Obbligatorio
    Description

    prototype o build. La raccolta restituisce solo le attività la cui fase corrisponde all'URL — richiamare /prototype non restituisce mai attività di build e viceversa.

Parametri della query

  • Name
    page_num
    Type
    integer
    predefinito 1
    Description

    Numero di pagina per la paginazione.

  • Name
    page_size
    Type
    integer
    predefinito 10
    Description

    Limite della dimensione della pagina. Il massimo consentito è 100 elementi.

  • Name
    sort_by
    Type
    string
    predefinito -created_at
    Description

    Campo per cui ordinare. Valori disponibili:

    • +created_at: Ordina per data di creazione in ordine crescente.
    • -created_at: Ordina per data di creazione in ordine decrescente.

Restituisce

Restituisce un elenco paginato dell'oggetto attività per fase — ovvero l'oggetto attività di prototipo keycap quando si elenca /prototype oppure l'oggetto attività di build keycap quando si elenca /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"
    ]
  }
]

L'oggetto Keycap Prototype Task

L'oggetto Keycap Prototype Task è un'unità di lavoro che Meshy tiene traccia per generare un'immagine di design del keycap finito a partire da una foto sorgente. L' output di questa fase viene concatenato a la fase di build tramite input_task_id più candidate_id.

Proprietà

  • Name
    id
    Type
    string
    Description

    Identificatore univoco per il task. Sebbene utilizziamo un UUID k-sortable per gli id dei task come dettaglio implementativo, non dovresti fare alcuna assunzione sul formato dell'id.

  • Name
    type
    Type
    string
    Description

    Tipo del task. Il valore è creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    Il nome del task fornito al momento della creazione. Stringa vuota se non è stato fornito alcun nome.

  • Name
    status
    Type
    string
    Description

    Stato del task. I valori possibili sono uno tra PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progresso del task. Se il task non è ancora iniziato, questa proprietà sarà 0. Una volta che il task ha avuto successo, diventerà 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Timestamp di quando il task è stato creato, in millisecondi.

  • Name
    started_at
    Type
    timestamp
    Description

    Timestamp di quando il task è stato avviato, in millisecondi. Se il task non è ancora iniziato, questa proprietà sarà 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Timestamp di quando il task è stato completato, in millisecondi. Se il task non è ancora terminato, questa proprietà sarà 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Timestamp di quando il risultato del task scade, in millisecondi.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Il conteggio dei task precedenti.

  • Name
    task_error
    Type
    object
    Description

    Dettagli dell'errore per i task falliti. Vedi Errori per il riferimento completo dell'oggetto task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Il numero di crediti consumati da questo task. Un task che raggiunge SUCCEEDED viene addebitato per l'importo completo relativo alla sua fase. Un task che non viene mai creato (un 4xx al momento della richiesta, inclusa una rifiuto da moderation) non viene addebitato affatto. Un task che raggiunge FAILED restituisce 0 — l'addebito viene rimborsato, incluso un blocco di moderation asincrono. Annullare tramite DELETE rimborsa solo mentre il task è ancora PENDING; un task già IN_PROGRESS rimane addebitato, poiché il lavoro è già stato speso.

  • Name
    image_urls
    Type
    array of strings
    Description

    URL scaricabile del render del design del keycap finito — come appare il candidato come keycap finito. Contiene una singola voce; image_urls[i] corrisponde a candidate_ids[i]. Vuoto finché il task non raggiunge SUCCEEDED. L'URL è solo per la visualizzazione; l'endpoint di build consuma candidate_ids, non questi URL. Stesso ciclo di vita dell'URL di model_urls: firmato, senza header Authorization, valido fino a expires_at, e stabile quando il task viene riletto.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Identificatori di candidati opachi, paralleli a image_urls. Passa la voce corrispondente al design scelto come candidate_id della richiesta di build. Non fare alcuna assunzione sul formato di questi 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"
  ]
}

The Keycap Build Task Object

L'oggetto Keycap Build Task è un'unità di lavoro che Meshy tiene traccia per generare il keycap 3D texturizzato finale a partire da un prototype task riuscito e da un candidato scelto. Un singolo build esegue l'intera pipeline — generazione del modello bianco, seating e taglio automatici, colorazione, assemblaggio ed esportazione.

Proprietà

  • Name
    id
    Type
    string
    Description

    Identificatore univoco per il task.

  • Name
    type
    Type
    string
    Description

    Tipo del task. Il valore è creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    Il nome del task fornito al momento della creazione. Stringa vuota se non è stato fornito alcun nome.

  • Name
    status
    Type
    string
    Description

    Stato del task. I valori possibili sono uno tra PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progress del task. Se il task non è ancora iniziato, questa proprietà sarà 0. Una volta che il task ha avuto successo, diventerà 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Timestamp di quando il task è stato creato, in millisecondi.

  • Name
    started_at
    Type
    timestamp
    Description

    Timestamp di quando il task è stato avviato, in millisecondi.

  • Name
    finished_at
    Type
    timestamp
    Description

    Timestamp di quando il task è stato completato, in millisecondi.

  • Name
    expires_at
    Type
    timestamp
    Description

    Timestamp di quando il risultato del task scade, in millisecondi.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Il conteggio dei task precedenti. Significativo solo quando lo status è PENDING.

  • Name
    task_error
    Type
    object
    Description

    Dettagli dell'errore per i task falliti. Vedi Errori per il riferimento completo dell'oggetto task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Il numero di crediti consumati da questo task. Un task che raggiunge lo stato SUCCEEDED viene addebitato per l'importo completo relativo alla sua fase. Un task che non viene mai creato (un 4xx al momento della richiesta, incluso un rifiuto di moderation) non viene addebitato affatto. Un task che raggiunge FAILED restituisce 0 — l'addebito viene rimborsato, incluso un blocco di moderation asincrono. L'annullamento tramite DELETE rimborsa solo mentre il task è ancora PENDING; un task già IN_PROGRESS rimane addebitato, poiché il lavoro è già stato svolto.

  • Name
    model_urls
    Type
    object
    Description

    URL scaricabili per gli artefatti del modello generato. Sia il bundle GLB che quello OBJ vengono esportati in scala millimetrica reale, Y-up, con la parte anteriore del keycap rivolta verso +Z. Le mesh sono denominate keycap-head e keycap-base; quando la base ricade su un riempimento a pattern, è presente anche una terza mesh keycap-base-interior per la cavità dello stem. Non dare per scontato che vi siano esattamente due mesh.

    Questi sono URL firmati: recuperali senza un header Authorization. Rimangono validi fino a expires_at, che è 3 giorni dopo finished_at, e rileggere il task all'interno di questa finestra temporale restituisce lo stesso URL identico anziché uno appena firmato. Scarica e archivia tu stesso i file prima di allora — non c'è modo di aggiornare un link scaduto.

    • Name
      glb
      Type
      string
      Description

      URL scaricabile per il model.glb texturizzato finale.

    • Name
      obj_zip
      Type
      string
      Description

      URL scaricabile per un bundle zip contenente model.obj, model.mtl, e i PNG delle texture effettivamente referenziati dal suo MTL. Una base a colore solido include solo keycap-head.png; una base a pattern include anche keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    URL scaricabili per le immagini di processo intermedie, indicizzate per tipo. Stesso ciclo di vita degli URL di model_urls: firmati, senza header Authorization, validi fino a expires_at, e stabili quando il task viene riletto. Tipi attualmente emessi:

    • head_design — l'immagine di design del candidato scelto consumata dal build (sempre presente).
    • composite — il render di visualizzazione del keycap finito relativo al candidato scelto (presente quando disponibile).
    • base_canvas — il canvas dipinto della base del keycap (presente quando disponibile).

    Considera l'insieme delle chiavi come aperto a estensioni; nuovi tipi potrebbero essere aggiunti senza che ciò costituisca una modifica incompatibile.

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

Il flusso completo: creare un prototipo da una foto, effettuarne il polling fino a SUCCEEDED, scegliere un candidato da candidate_ids, creare una build con quel candidato, effettuare il polling della build fino a SUCCEEDED, quindi scaricare il GLB e il pacchetto OBJ da model_urls.

L'esempio sceglie programmaticamente il primo candidato. In un'integrazione reale mostreresti la voce image_urls all'utente finale e lo lasceresti scegliere; l'indice scelto corrisponde 1:1 a 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"