Creative Lab — Keycap API

Verwandeln Sie ein Ausgangsfoto in zwei Stufen in eine vollfarbige, individuelle mechanische Tastatur-Keycap: Prototype erzeugt aus Ihrem Eingabefoto ein Render-Design einer „fertigen Keycap“. Sobald Sie dieses Render bestätigt haben, wandelt Build es in einem einzigen Durchlauf in ein texturiertes 3D-Keycap-Modell um — White-Model-Generierung, automatisches Einpassen und Zuschneiden auf einer kalibrierten Standardpose, vollständige Modellkolorierung und abschließende Zusammensetzung finden alle innerhalb eines einzigen Build-Tasks statt. Die beiden Stufen sind über input_task_id sowie candidate_id miteinander verknüpft.

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

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

Erstellen einer Keycap-Prototyp-Aufgabe

Erzeugt aus dem Ausgangsfoto einen fertigen Keycap-Design-Render. Das Ergebnis der Aufgabe enthält ein image_urls-Array (den Anzeige-Render der fertigen Keycap) und ein paralleles candidate_ids-Array; beide enthalten jeweils einen einzelnen Eintrag. Rufen Sie diesen Endpunkt erneut auf, um einen weiteren Render zu erhalten, falls das Ergebnis nicht Ihren Vorstellungen entspricht — jeder Aufruf wird separat abgerechnet. Übergeben Sie die candidate_id zusammen mit der Prototyp-Aufgaben-ID an den Build-Endpunkt. Die Form der Antwort finden Sie unter Das Keycap-Prototyp-Aufgabenobjekt.

Parameter

  • Name
    image_url
    Type
    string
    Erforderlich
    Description

    Ausgangsfoto, das Meshy in Keycap-Design-Bilder umwandeln soll. Wir unterstützen derzeit die Formate .jpg, .jpeg, .png und .webp.

    Das Format wird durch Dekodierung der Bilddaten erkannt, nicht anhand der Dateiendung der URL — eine URL ohne Dateiendung oder eine, die weiterleitet, funktioniert, solange sich die Bytes zu einem unterstützten Format dekodieren lassen. HTTP-Weiterleitungen werden verfolgt. Die EXIF-Ausrichtung wird normalisiert, sodass ein gedrehtes Handyfoto so verwendet wird, wie es aussieht.

    Grenzwerte: mindestens 32 Pixel pro Seite, höchstens 178.956.970 Pixel insgesamt und höchstens 20.000.000 Bytes nach dem Herunterladen. Bei einer Data URI gilt die Grenze für die dekodierten Bytes, sodass die Quelldatei selbst bis zu dieser Größe groß sein darf — es ist der Base64-Text, der etwa ein Drittel größer ist, was für Ihren Request-Body relevant ist, nicht für diese Grenze. Eine Data URI muss einen image/*-Content-Type und ;base64 angeben.

    Es gibt zwei Möglichkeiten, das Bild bereitzustellen:

    • Öffentlich zugängliche URL: Eine URL, die aus dem öffentlichen Internet erreichbar ist.
    • Data URI: Eine base64-kodierte Data URI des Bildes. Beispiel für eine Data URI: data:image/jpeg;base64,<Ihre base64-kodierten Bilddaten>.
  • Name
    name
    Type
    string
    Description

    Optionaler Aufgabenname zu Anzeigezwecken. Maximal 100 Zeichen.

  • Name
    remove_background
    Type
    boolean
    Standard false
    Description

    Wenn dies auf true gesetzt ist, ist der in image_urls zurückgegebene Anzeige-Render ein transparentes RGBA-PNG mit entferntem Hintergrund, sodass Sie es auf einen beliebigen Hintergrund legen können.

    Dies gilt nur für den Anzeige-Render. Der Kandidat, den der Build-Endpunkt verwendet, ist davon nicht betroffen, sodass das 3D-Ergebnis in beiden Fällen identisch ist.

Rückgabewerte

Die Eigenschaft result der Antwort enthält die Aufgaben-id der neu erstellten Keycap-Prototyp-Aufgabe. Fragen Sie den Get a Task-Endpunkt ab oder abonnieren Sie den Stream, bis die Aufgabe den Status SUCCEEDED erreicht, und übernehmen Sie dann den Eintrag aus candidate_ids und übergeben Sie ihn zusammen mit der Aufgaben-ID an den Build-Endpunkt.

Fehlermodi

  • Name
    400 - Bad Request
    Description

    Die Anfrage war nicht akzeptabel. Häufige Ursachen:

    • Fehlender Parameter: image_url ist erforderlich.
    • Ungültiges Bildformat: Die angegebene image_url liegt nicht in einem unterstützten Format vor (.jpg, .jpeg, .png, .webp).
    • Bildabmessungen außerhalb des zulässigen Bereichs: Das Bild ist zu klein, überschreitet die maximale Dateigröße oder überschreitet die maximale Pixelanzahl.
    • Nicht erreichbare URL: Die image_url konnte nicht heruntergeladen werden (404 oder timeout).
    • Ungültige Data URI: Die Base64-Zeichenfolge ist fehlerhaft.
    • Inhalt markiert: Das Eingabebild wurde durch die NSFW-moderation markiert.
  • Name
    401 - Unauthorized
    Description

    Die Authentifizierung ist fehlgeschlagen. Bitte überprüfen Sie Ihren API-Schlüssel.

  • Name
    402 - Payment Required
    Description

    Das Konto befindet sich im kostenlosen Plan (für das Erstellen von Aufgaben ist ein kostenpflichtiger Plan erforderlich) oder verfügt über nicht ausreichende Credits.

  • Name
    403 - Forbidden
    Description

    Das Eingabebild wurde durch die moderation für geistiges Eigentum markiert.

  • Name
    429 - Too Many Requests
    Description

    Sie haben Ihre Ratenbegrenzung überschritten.

  • Name
    500 - Internal Server Error
    Description

    Ein unerwarteter serverseitiger Fehler ist aufgetreten — zum Beispiel war der Content-moderation-Dienst nicht verfügbar, das Bereitstellen des Eingabebilds ist fehlgeschlagen, oder die Aufgabe konnte nicht erstellt werden. In diesem Fall wird keine Aufgabe erstellt, sodass ein erneuter Versuch unbedenklich ist.

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

Erstellen einer Keycap-Build-Aufgabe

Generiert das finale texturierte 3D-Keycap-Modell aus einer erfolgreichen Prototype-Aufgabe und einem ihrer Kandidaten. Eine einzelne Build-Aufgabe durchläuft die gesamte Pipeline von Anfang bis Ende – White-Model-Generierung aus dem gewählten Design, automatisches Aufsetzen und Zuschneiden auf die Keycap-Basis unter Verwendung einer kalibrierten Standardpose (keine interaktive Anpassung erforderlich), vollständige Modellfärbung sowie finale Zusammenstellung und Export. Ein Build dauert in der Regel 3–7 Minuten, tendenziell eher am oberen Ende, wenn mehrere Builds gleichzeitig laufen. Siehe Das Keycap-Build-Task-Objekt für die Form der Antwort.

Parameter

  • Name
    input_task_id
    Type
    string
    Erforderlich
    Description

    Die Task-ID einer über denselben OpenAPI-Endpunkt erstellten Prototype-Aufgabe. Der Prototyp muss vom selben Meshy-Konto erstellt worden sein, muss den Status SUCCEEDED erreicht haben und muss mindestens einen Kandidaten hervorgebracht haben.

    Über die Webapp erstellte Prototype-Aufgaben werden nicht akzeptiert – der Build-Endpunkt akzeptiert nur Prototype-Aufgaben, die von POST /openapi/creative-lab/keycap/v1/prototype erzeugt wurden, und lehnt jede andere Quelle mit 404 ab.

  • Name
    candidate_id
    Type
    string
    Erforderlich
    Description

    Der zu bauende Kandidat, entnommen aus dem candidate_ids-Array der erfolgreichen Prototype-Aufgabe. Muss zu dieser Aufgabe gehören; jeder andere Wert wird mit 400 abgelehnt.

  • Name
    name
    Type
    string
    Description

    Optionaler Aufgabenname für Anzeigezwecke. Maximal 100 Zeichen.

options

Optionale Geometrie-Feinabstimmung. Jedes Feld hat einen kalibrierten Standardwert – senden Sie nur die Felder, die Sie überschreiben möchten.

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

    Die Keycap-Basis, auf der gebaut werden soll. Derzeit ist der einzige verfügbare Wert cherry-mx-1x1-r1 – eine Standard-Cherry-MX-Profil-1u-Keycap. 3–5 zusätzliche gängige Standardgrößen sind geplant; benutzerdefinierte Größen werden nicht unterstützt.

  • Name
    head_size_mm
    Type
    number
    Standard 23
    Description

    Zielgröße des gestalteten Kopfes in Millimetern: seine längste Abmessung wird auf diesen Wert skaliert. Bereich: [10, 40]. Werte über etwa 32,9 können reduziert werden, damit der Kopf weiterhin innerhalb der Schutz-Grundflächenbegrenzung der Basis liegt, sodass die gelieferte längste Abmessung kleiner sein kann als angefordert. Der angewendete Wert wird derzeit nicht im Task-Objekt zurückgemeldet – wenn Sie die tatsächlich erhaltene Größe überprüfen möchten, messen Sie den Begrenzungsrahmen des keycap-head-Netzes im heruntergeladenen Modell.

  • Name
    vertical_offset_mm
    Type
    number
    Standard 0
    Description

    Vertikaler Versatz, der auf den Kopf angewendet wird, bevor er auf der Basis aufgesetzt wird, in Millimetern. Bereich: [-5, 5].

Rückgabe

Die result-Eigenschaft der Antwort enthält die Task-id der neu erstellten Keycap-Build-Aufgabe. Fragen Sie den Get a Task-Endpunkt ab oder abonnieren Sie den Stream, bis die Aufgabe den Status SUCCEEDED erreicht, und laden Sie dann die Artefakte von model_urls.glb und model_urls.obj_zip herunter.

Fehlerfälle

  • Name
    400 - Bad Request
    Description

    Die Anfrage war nicht akzeptabel. Häufige Ursachen:

    • Fehlender Parameter: input_task_id und candidate_id sind erforderlich.
    • Ungültige UUID: Die input_task_id ist keine gültige UUID.
    • Übergeordnete Aufgabe nicht erfolgreich: Die referenzierte Prototype-Aufgabe hat noch nicht den Status SUCCEEDED erreicht.
    • Keine Kandidaten: Die Prototype-Aufgabe war erfolgreich, hat aber keine Kandidaten hervorgebracht.
    • Unbekannter Kandidat: candidate_id gehört nicht zu den Kandidaten der Eingabeaufgabe.
    • Optionen außerhalb des zulässigen Bereichs: Eines der options-Felder lag außerhalb seines zulässigen Bereichs oder Enum-Satzes.
  • Name
    401 - Unauthorized
    Description

    Die Authentifizierung ist fehlgeschlagen. Bitte überprüfen Sie Ihren API-Schlüssel.

  • Name
    402 - Payment Required
    Description

    Das Konto befindet sich im kostenlosen Plan (für das Erstellen von Aufgaben ist ein kostenpflichtiger Plan erforderlich) oder verfügt über nicht ausreichende Credits.

  • Name
    404 - Not Found
    Description

    Die referenzierte Prototype-Aufgabe existiert nicht, gehört einem anderen Benutzer, oder wurde über die Webapp erstellt (nur Prototype-Aufgaben im API-Modus können in ein Build übergehen).

  • Name
    429 - Too Many Requests
    Description

    Sie haben Ihre Ratenbegrenzung überschritten.

  • Name
    500 - Internal Server Error
    Description

    Es ist ein unerwarteter serverseitiger Fehler aufgetreten – zum Beispiel war der Content-Moderation-Dienst nicht verfügbar, das Bereitstellen des Eingabebilds ist fehlgeschlagen, oder die Aufgabe konnte nicht erstellt werden. In diesem Fall wird keine Aufgabe erstellt, sodass ein erneuter Versuch unbedenklich ist.

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

Einen Keycap-Task abrufen

Ruft einen Prototype- oder Build-Task anhand einer gültigen Task-id ab. Der URL-Pfad muss mit der Stufe des Tasks übereinstimmen — ein Build-Task, der über /prototype/:id abgerufen wird, liefert 404, und umgekehrt.

Die Antwortformate finden Sie unter Das Keycap-Prototype-Task-Objekt und Das Keycap-Build-Task-Objekt.

Parameter

  • Name
    id
    Type
    path
    Description

    Eindeutige Kennung des abzurufenden Keycap-Tasks.

Rückgabe

Die Antwort enthält das Keycap-Task-Objekt. Die Form hängt davon ab, welche Stufe angefordert wurde.

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

Eine Keycap-Aufgabe löschen

Bricht eine Keycap-Aufgabe ab. Wenn sich die Aufgabe noch im Status PENDING befindet, werden die bei der Erstellung verbrauchten Credits zurückerstattet. Aufgaben, die sich bereits IN_PROGRESS befinden, werden ohne Rückerstattung abgebrochen (der Worker verbraucht möglicherweise bereits Ressourcen). Aufgaben, die bereits einen endgültigen Status erreicht haben (SUCCEEDED, FAILED, CANCELED), können nicht abgebrochen werden.

Der URL-Pfad muss mit der Phase der Aufgabe übereinstimmen — ein DELETE auf /prototype/:buildId liefert 404.

Pfadparameter

  • Name
    id
    Type
    path
    Description

    Eindeutige Kennung der abzubrechenden Keycap-Aufgabe.

Rückgabewerte

Gibt bei Erfolg 204 No Content mit leerem Inhalt zurück.

Fehlerarten

  • Name
    400 - Bad Request
    Description

    Die Aufgabe befindet sich bereits in einem endgültigen Status und kann nicht abgebrochen werden.

  • Name
    404 - Not Found
    Description

    Die Aufgabe existiert nicht, gehört einem anderen Benutzer oder ihre Phase stimmt nicht mit dem URL-Pfad überein.

  • Name
    500 - Internal Server Error
    Description

    Beim Abbrechen ist ein unerwarteter serverseitiger Fehler aufgetreten. Die Aufgabe wurde möglicherweise abgebrochen oder auch nicht — lesen Sie sie erneut aus, um dies vor einem erneuten Versuch zu bestätigen.

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 einer Keycap-Aufgabe

Streamen Sie Echtzeit-Updates für eine Keycap-Aufgabe über Server-Sent Events (SSE). Der URL-Pfad muss der Phase der Aufgabe entsprechen — wird ein Stream unter /prototype/:buildId/stream geöffnet, obwohl sich die Aufgabe in einer anderen Phase befindet, wird ein einzelner event: error-Payload mit status_code: 404 gesendet und der Stream geschlossen.

Parameter

  • Name
    id
    Type
    path
    Description

    Eindeutige Kennung der zu streamenden Keycap-Aufgabe.

Rückgabewerte

Gibt einen Stream von Keycap-Prototyp- oder Keycap-Build-Aufgabenobjekten als Server-Sent Events zurück. Jeder Frame enthält das vollständige Aufgabenobjekt für die jeweilige Phase — dieselbe Struktur, die der Get-Endpunkt zurückgibt — solange die Aufgabe also PENDING oder IN_PROGRESS ist, sind die Ausgabefelder einfach noch nicht befüllt (null, [] oder {}) und finished_at ist null.

Request

GET
/openapi/creative-lab/keycap/v1/build/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/stream
curl -N https://api.meshy.ai/openapi/creative-lab/keycap/v1/build/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/stream \
-H "Authorization: Bearer ${YOUR_API_KEY}"

Response Stream

// Error event example (wrong stage or task not found)
event: error
data: {
  "status_code": 404,
  "message": "Task not found"
}

// Message event examples illustrate task progress.
// Every frame is the full task object; fields not yet populated are null / empty.
// The PENDING frame below is abbreviated to the fields that change.
event: message
data: {
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "progress": 0,
  "status": "PENDING"
}

event: message
data: {
  "id": "019c9a52-7d18-7e2b-9f01-6e3b98c4d2af",
  "type": "creative-lab-keycap-build",
  "status": "SUCCEEDED",
  "progress": 100,
  "created_at": 1753142600000,
  "started_at": 1753142610000,
  "finished_at": 1753143050000,
  "expires_at": 1753402250000,
  "task_error": null,
  "consumed_credits": 50,
  "model_urls": {
    "glb": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model.glb?Expires=***",
    "obj_zip": "https://assets.meshy.ai/***/tasks/019c9a52-7d18-7e2b-9f01-6e3b98c4d2af/output/model-obj.zip?Expires=***"
  },
  "process_image_urls": {
    "head_design": "https://assets.meshy.ai/***/head-design.png?Expires=***"
  }
}

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

List Keycap Tasks

Ruft eine paginierte Liste Ihrer Keycap-Tasks für eine einzelne Stufe ab. Der URL- Pfad wählt die Stufe aus — /prototype liefert Prototyp-Tasks; /build liefert Build-Tasks. Tasks der jeweils anderen Stufe sind in keiner der beiden Antworten enthalten.

Pfadparameter

  • Name
    stage
    Type
    path
    Erforderlich
    Description

    Entweder prototype oder build. Die Auflistung liefert nur Tasks zurück, deren Stufe mit der URL übereinstimmt — das Abrufen von /prototype liefert niemals Build-Tasks zurück und umgekehrt.

Query-Parameter

  • Name
    page_num
    Type
    integer
    Standard 1
    Description

    Seitenzahl für die Paginierung.

  • Name
    page_size
    Type
    integer
    Standard 10
    Description

    Begrenzung der Seitengröße. Maximal zulässig sind 100 Einträge.

  • Name
    sort_by
    Type
    string
    Standard -created_at
    Description

    Feld, nach dem sortiert werden soll. Verfügbare Werte:

    • +created_at: Sortierung nach Erstellungszeitpunkt in aufsteigender Reihenfolge.
    • -created_at: Sortierung nach Erstellungszeitpunkt in absteigender Reihenfolge.

Rückgabewerte

Liefert eine paginierte Liste des Task-Objekts der jeweiligen Stufe — entweder das Keycap-Prototyp-Task-Objekt beim Auflisten von /prototype oder das Keycap-Build-Task-Objekt beim Auflisten von /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"
    ]
  }
]

Das Keycap Prototype Task-Objekt

Das Keycap Prototype Task-Objekt ist eine Arbeitseinheit, die Meshy verfolgt, um aus einem Ausgangsfoto ein Bild des fertigen Keycap-Designs zu erzeugen. Die Ausgabe dieser Stufe wird über input_task_id zusammen mit candidate_id mit der Build-Stufe verkettet.

Eigenschaften

  • Name
    id
    Type
    string
    Description

    Eindeutiger Bezeichner für die Aufgabe. Wir verwenden als Implementierungsdetail eine k-sortierbare UUID für Task-IDs, du solltest jedoch keine Annahmen über das Format der ID treffen.

  • Name
    type
    Type
    string
    Description

    Typ der Aufgabe. Der Wert ist creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    Der beim Erstellen der Aufgabe angegebene Aufgabenname. Leerer String, wenn kein Name angegeben wurde.

  • Name
    status
    Type
    string
    Description

    Status der Aufgabe. Mögliche Werte sind PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Fortschritt der Aufgabe. Wenn die Aufgabe noch nicht gestartet wurde, ist dieser Wert 0. Sobald die Aufgabe erfolgreich abgeschlossen wurde, wird er 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Zeitstempel, wann die Aufgabe erstellt wurde, in Millisekunden.

  • Name
    started_at
    Type
    timestamp
    Description

    Zeitstempel, wann die Aufgabe gestartet wurde, in Millisekunden. Wenn die Aufgabe noch nicht gestartet wurde, ist dieser Wert 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Zeitstempel, wann die Aufgabe abgeschlossen wurde, in Millisekunden. Wenn die Aufgabe noch nicht abgeschlossen ist, ist dieser Wert 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Zeitstempel, wann das Ergebnis der Aufgabe abläuft, in Millisekunden.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Die Anzahl der vorausgehenden Aufgaben.

  • Name
    task_error
    Type
    object
    Description

    Fehlerdetails für fehlgeschlagene Aufgaben. Siehe Fehler für die vollständige Referenz des task_error-Objekts.

  • Name
    consumed_credits
    Type
    integer
    Description

    Die Anzahl der von dieser Aufgabe verbrauchten Credits. Bei einer Aufgabe, die SUCCEEDED erreicht, wird der volle Betrag für ihre Stufe berechnet. Eine Aufgabe, die nie erstellt wird (ein 4xx zum Zeitpunkt der Anfrage, einschließlich einer moderation-Ablehnung), wird überhaupt nicht berechnet. Eine Aufgabe, die FAILED erreicht, gibt 0 zurück — der Betrag wird erstattet, einschließlich eines asynchronen moderation-Blocks. Ein Abbruch per DELETE erstattet nur, solange die Aufgabe noch PENDING ist; eine bereits IN_PROGRESS befindliche Aufgabe bleibt berechnet, da die Arbeit bereits geleistet wurde.

  • Name
    image_urls
    Type
    array of strings
    Description

    Herunterladbare URL des gerenderten fertigen Keycap-Designs — wie der Kandidat als fertiger Keycap aussieht. Enthält genau einen Eintrag; image_urls[i] entspricht candidate_ids[i]. Leer, bis die Aufgabe SUCCEEDED erreicht. Die URL dient nur zur Anzeige; der Build-Endpunkt verarbeitet candidate_ids, nicht diese URLs. Gleicher URL-Lebenszyklus wie model_urls: signiert, kein Authorization-Header, gültig bis expires_at, und stabil beim erneuten Lesen der Aufgabe.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Undurchsichtige Kandidaten-Bezeichner, parallel zu image_urls. Übergib den Eintrag, der deinem gewählten Design entspricht, als candidate_id der Build-Anfrage. Triff keine Annahmen über das Format dieser IDs.

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

Das Keycap-Build-Task-Objekt

Das Keycap-Build-Task-Objekt ist eine Arbeitseinheit, die Meshy verfolgt, um aus einer erfolgreichen Prototyp-Task und einem ausgewählten Kandidaten die finale texturierte 3D-Keycap zu erzeugen. Ein einzelner Build durchläuft die gesamte Pipeline — Weißmodell-Generierung, automatisches Einpassen und Zuschneiden, Kolorierung, Zusammenbau und Export.

Eigenschaften

  • Name
    id
    Type
    string
    Description

    Eindeutige Kennung für die Task.

  • Name
    type
    Type
    string
    Description

    Typ der Task. Der Wert ist creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    Der beim Erstellen der Task angegebene Name. Leerer String, wenn kein Name angegeben wurde.

  • Name
    status
    Type
    string
    Description

    Status der Task. Mögliche Werte sind PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Fortschritt der Task. Wenn die Task noch nicht gestartet wurde, hat diese Eigenschaft den Wert 0. Sobald die Task erfolgreich war, wird dieser Wert 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Zeitstempel, wann die Task erstellt wurde, in Millisekunden.

  • Name
    started_at
    Type
    timestamp
    Description

    Zeitstempel, wann die Task gestartet wurde, in Millisekunden.

  • Name
    finished_at
    Type
    timestamp
    Description

    Zeitstempel, wann die Task beendet wurde, in Millisekunden.

  • Name
    expires_at
    Type
    timestamp
    Description

    Zeitstempel, wann das Ergebnis der Task abläuft, in Millisekunden.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Die Anzahl vorausgehender Tasks. Nur relevant, wenn der Status PENDING ist.

  • Name
    task_error
    Type
    object
    Description

    Fehlerdetails für fehlgeschlagene Tasks. Die vollständige Referenz zum task_error-Objekt finden Sie unter Fehler.

  • Name
    consumed_credits
    Type
    integer
    Description

    Die Anzahl der von dieser Task verbrauchten Credits. Einer Task, die SUCCEEDED erreicht, wird der volle Betrag für ihre Phase berechnet. Eine Task, die nie erstellt wird (ein 4xx zum Zeitpunkt der Anfrage, einschließlich einer Ablehnung durch die moderation), wird überhaupt nicht berechnet. Eine Task, die FAILED erreicht, gibt 0 zurück — die Gebühr wird erstattet, einschließlich eines asynchronen moderation-Blocks. Ein Abbrechen über DELETE erstattet die Gebühr nur, solange die Task noch PENDING ist; eine bereits IN_PROGRESS befindliche Task bleibt kostenpflichtig, da die Arbeit bereits geleistet wurde.

  • Name
    model_urls
    Type
    object
    Description

    Herunterladbare URLs für die generierten Modell-Artefakte. Sowohl das GLB- als auch das OBJ-Bundle werden im realen Maßstab in Millimetern, mit Y-nach-oben, exportiert, wobei die Vorderseite der Keycap nach +Z zeigt. Die Netze heißen keycap-head und keycap-base; wenn die Basis auf eine Musterfüllung zurückgreift, ist zusätzlich ein drittes Netz keycap-base-interior für den Stem-Hohlraum vorhanden. Gehen Sie nicht davon aus, dass es genau zwei Netze gibt.

    Dies sind signierte URLs: Rufen Sie sie ohne einen Authorization-Header ab. Sie bleiben gültig bis expires_at, was 3 Tage nach finished_at liegt, und ein erneutes Lesen der Task innerhalb dieses Zeitfensters liefert dieselbe URL zurück statt einer neu signierten. Laden Sie die Dateien vorher selbst herunter und speichern Sie sie — es gibt keine Möglichkeit, einen abgelaufenen Link zu erneuern.

    • Name
      glb
      Type
      string
      Description

      Herunterladbare URL zur finalen texturierten model.glb.

    • Name
      obj_zip
      Type
      string
      Description

      Herunterladbare URL zu einem ZIP-Bundle mit model.obj, model.mtl und den Textur-PNGs, auf die dessen MTL tatsächlich verweist. Eine Basis in Vollfarbe liefert nur keycap-head.png; eine gemusterte Basis liefert zusätzlich keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    Herunterladbare URLs für zwischengeschaltete Prozessbilder, geschlüsselt nach Art. Gleicher URL-Lebenszyklus wie bei model_urls: signiert, kein Authorization-Header, gültig bis expires_at und stabil bei erneutem Lesen der Task. Aktuell ausgegebene Arten:

    • head_design — das vom Build verwendete Designbild des gewählten Kandidaten (immer vorhanden).
    • composite — das fertige Anzeige-Rendering der ausgewählten Keycap des gewählten Kandidaten (vorhanden, wenn verfügbar).
    • base_canvas — die bemalte Keycap-Basis-Leinwand (vorhanden, wenn verfügbar).

    Betrachten Sie die Menge der Schlüssel als offen; neue Arten können hinzugefügt werden, ohne eine breaking change darzustellen.

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

Der vollständige Ablauf: ein Prototyp wird aus einem Foto erstellt, per Polling bis SUCCEEDED abgefragt, ein Kandidat wird aus candidate_ids ausgewählt, mit diesem Kandidaten ein Build erstellt, der Build per Polling bis SUCCEEDED abgefragt und anschließend werden das GLB und das OBJ-Bundle aus model_urls heruntergeladen.

Das Beispiel wählt programmatisch den ersten Kandidaten aus. In einer echten Integration würde man dem Endnutzer den jeweiligen image_urls-Eintrag anzeigen und ihn auswählen lassen; der gewählte Index wird 1:1 auf candidate_ids abgebildet.

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"