Creative Lab — API Keycap

Transformez une photo source en une touche de clavier mécanique personnalisée en couleur en deux étapes : prototype génère un rendu de conception de "touche finie" à partir de votre photo d'entrée. Une fois que vous avez confirmé ce rendu, build le transforme en un modèle 3D de touche texturée en une seule exécution — génération de modèle blanc, positionnement et découpe automatiques sur une pose par défaut calibrée, coloration complète du modèle, et assemblage final se produisent tous dans une seule tâche de construction. Les deux étapes sont liées 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

Créer une Tâche de Prototype de Keycap

Générer un rendu de design de keycap fini à partir de la photo source. Le résultat de la tâche contient un tableau image_urls (le rendu d'affichage du keycap fini) et un tableau parallèle candidate_ids; les deux contiennent une seule entrée. Appelez à nouveau ce point de terminaison pour un autre rendu si le résultat ne vous convient pas — chaque appel est facturé séparément. Passez le candidate_id avec l'ID de la tâche prototype au point de terminaison de construction. Référez-vous à L'Objet de Tâche Prototype de Keycap pour la forme de la réponse.

Paramètres

  • Name
    image_url
    Type
    string
    Requis
    Description

    Photo source pour que Meshy la transforme en images de design de keycap. Nous supportons actuellement les formats .jpg, .jpeg, .png, et .webp.

    Le format est détecté en décodant les données de l'image, pas à partir de l'extension de fichier de l'URL — une URL sans extension, ou une qui redirige, fonctionne tant que les octets se décodent dans un format supporté. Les redirections HTTP sont suivies. L'orientation EXIF est normalisée, donc une photo de téléphone tournée est utilisée telle qu'elle apparaît.

    Limites : au moins 32 pixels de chaque côté, au maximum 178,956,970 pixels au total, et au maximum 20,000,000 octets une fois téléchargée. Pour un Data URI, la limite s'applique aux octets décodés, donc le fichier source lui-même peut atteindre cette taille — c'est le texte base64 qui est environ un tiers plus grand, ce qui compte pour votre corps de requête, pas pour cette limite. Un Data URI doit déclarer un type de contenu image/* et ;base64.

    Il y a deux façons de fournir l'image :

    • URL accessible publiquement : Une URL accessible depuis l'internet public.
    • Data URI : Un Data URI encodé en base64 de l'image. Exemple de Data URI : data:image/jpeg;base64,<vos données d'image encodées en base64>.
  • Name
    name
    Type
    string
    Description

    Nom de tâche optionnel à des fins d'affichage. Maximum 100 caractères.

  • Name
    remove_background
    Type
    boolean
    défaut false
    Description

    Lorsqu'il est réglé sur true, le rendu d'affichage retourné dans image_urls est un PNG RGBA transparent avec le fond supprimé, vous pouvez donc le composer sur n'importe quel fond.

    Cela s'applique uniquement au rendu d'affichage. Le candidat que le point de terminaison de construction consomme n'est pas affecté, donc le résultat 3D est identique dans les deux cas.

Retours

La propriété result de la réponse contient l'id de la tâche de prototype de keycap nouvellement créée. Interrogez le point de terminaison Obtenir une Tâche ou abonnez-vous au flux jusqu'à ce que la tâche atteigne SUCCEEDED, puis prenez l'entrée de candidate_ids et passez-la, avec l'ID de la tâche, au point de terminaison de construction.

Modes d'Échec

  • Name
    400 - Bad Request
    Description

    La requête était inacceptable. Causes courantes :

    • Paramètre manquant : image_url est requis.
    • Format d'image invalide : Le image_url fourni n'est pas un format supporté (.jpg, .jpeg, .png, .webp).
    • Dimensions de l'image hors limites : L'image est trop petite, dépasse la taille de fichier maximale, ou dépasse le nombre maximal de pixels.
    • URL inaccessible : Le image_url n'a pas pu être téléchargé (404 ou timeout).
    • Data URI invalide : La chaîne base64 est mal formée.
    • Contenu signalé : L'image d'entrée a été signalée par la modération NSFW.
  • Name
    401 - Unauthorized
    Description

    L'authentification a échoué. Veuillez vérifier votre clé API.

  • Name
    402 - Payment Required
    Description

    Le compte est sur le plan gratuit (un plan payant est requis pour créer des tâches) ou n'a pas suffisamment de crédits.

  • Name
    403 - Forbidden
    Description

    L'image d'entrée a été signalée par la modération de propriété intellectuelle.

  • Name
    429 - Too Many Requests
    Description

    Vous avez dépassé votre limite de débit.

  • Name
    500 - Internal Server Error
    Description

    Une erreur inattendue côté serveur s'est produite — par exemple, le service de modération de contenu était indisponible, la mise en scène de l'image d'entrée a échoué, ou la tâche n'a pas pu être créée. Aucune tâche n'est créée dans ce cas, donc réessayer est sans risque.

Requête

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

Réponse

{
  "result": "019c9a4e-2b31-7f6a-8c44-5d2a87b3c1ef"
}

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

Créer une Tâche de Construction de Keycap

Générer le modèle 3D final avec texture de la touche à partir d'une tâche prototype réussie et de l'un de ses candidats. Une seule tâche de construction exécute l'ensemble du pipeline de bout en bout — génération de modèle blanc à partir du design choisi, positionnement et découpe automatiques sur la base de la touche à l'aide d'une pose par défaut calibrée (aucun ajustement interactif nécessaire), coloration complète du modèle, et assemblage final et exportation. Une construction prend généralement 3 à 7 minutes, vers la limite supérieure lorsque plusieurs constructions sont exécutées simultanément. Référez-vous à L'Objet Tâche de Construction de Keycap pour la forme de la réponse.

Paramètres

  • Name
    input_task_id
    Type
    string
    Requis
    Description

    L'ID de la tâche prototype créée via ce même point de terminaison OpenAPI. Le prototype doit avoir été créé par le même compte Meshy, doit avoir atteint SUCCEEDED, et doit avoir produit au moins un candidat.

    Les tâches prototype créées via l'application web ne sont pas acceptées — le point de terminaison de construction accepte uniquement les tâches prototype produites par POST /openapi/creative-lab/keycap/v1/prototype et refuse toute autre source avec 404.

  • Name
    candidate_id
    Type
    string
    Requis
    Description

    Le candidat à construire, pris dans le tableau candidate_ids de la tâche prototype réussie. Doit appartenir à cette tâche ; toute autre valeur est rejetée avec 400.

  • Name
    name
    Type
    string
    Description

    Nom de tâche optionnel à des fins d'affichage. Maximum 100 caractères.

options

Réglage optionnel de la géométrie. Chaque champ a une valeur par défaut calibrée — envoyez uniquement ceux que vous souhaitez remplacer.

  • Name
    base_model
    Type
    string
    défaut cherry-mx-1x1-r1
    Description

    La base de la touche à construire. Actuellement, la seule valeur disponible est cherry-mx-1x1-r1 — une touche standard de profil Cherry MX 1u. 3 à 5 tailles standard grand public supplémentaires sont prévues ; les tailles personnalisées ne sont pas prises en charge.

  • Name
    head_size_mm
    Type
    number
    défaut 23
    Description

    Taille cible de la tête sculptée, en millimètres : sa plus grande dimension est mise à l'échelle à cette valeur. Plage : [10, 40]. Les valeurs supérieures à environ 32.9 peuvent être réduites pour que la tête s'adapte toujours à la limite de l'empreinte de protection de la base, de sorte que la plus grande dimension livrée peut être inférieure à celle demandée. La valeur appliquée n'est pas renvoyée aujourd'hui sur l'objet tâche — si vous devez confirmer la taille que vous avez réellement reçue, mesurez la boîte englobante du maillage keycap-head dans le modèle téléchargé.

  • Name
    vertical_offset_mm
    Type
    number
    défaut 0
    Description

    Décalage vertical appliqué à la tête avant qu'elle ne soit placée sur la base, en millimètres. Plage : [-5, 5].

Retours

La propriété result de la réponse contient l'id de la tâche de construction de keycap nouvellement créée. Interrogez le point de terminaison Obtenir une Tâche ou abonnez-vous au flux jusqu'à ce que la tâche atteigne SUCCEEDED, puis téléchargez les artefacts depuis model_urls.glb et model_urls.obj_zip.

Modes d'Échec

  • Name
    400 - Bad Request
    Description

    La requête était inacceptable. Causes courantes :

    • Paramètre manquant : input_task_id et candidate_id sont requis.
    • UUID invalide : Le input_task_id n'est pas un UUID valide.
    • Parent non réussi : La tâche prototype référencée n'a pas encore atteint SUCCEEDED.
    • Aucun candidat : La tâche prototype a réussi mais n'a produit aucun candidat.
    • Candidat inconnu : candidate_id n'est pas l'un des candidats de la tâche d'entrée.
    • Options hors plage : L'un des champs options est tombé en dehors de sa plage autorisée ou de son ensemble d'énumération.
  • Name
    401 - Unauthorized
    Description

    L'authentification a échoué. Veuillez vérifier votre clé API.

  • Name
    402 - Payment Required
    Description

    Le compte est sur le plan gratuit (un plan payant est requis pour créer des tâches) ou n'a pas suffisamment de crédits.

  • Name
    404 - Not Found
    Description

    La tâche prototype référencée n'existe pas, appartient à un utilisateur différent, ou a été créée via l'application web (seules les tâches prototype en mode API s'enchaînent dans la construction).

  • Name
    429 - Too Many Requests
    Description

    Vous avez dépassé votre limite de débit.

  • Name
    500 - Internal Server Error
    Description

    Une erreur inattendue côté serveur s'est produite — par exemple, le service de modération de contenu était indisponible, la mise en scène de l'image d'entrée a échoué, ou la tâche n'a pas pu être créée. Aucune tâche n'est créée dans ce cas, donc réessayer est sans danger.

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

Récupérer une Tâche de Keycap

Récupérer une tâche de prototype ou de construction donnée avec un id de tâche valide. Le chemin de l'URL doit correspondre à l'étape de la tâche — une tâche de construction récupérée via /prototype/:id renvoie 404, et vice versa.

Référez-vous à L'Objet de Tâche de Prototype de Keycap et L'Objet de Tâche de Construction de Keycap pour les formes de réponse.

Paramètres

  • Name
    id
    Type
    path
    Description

    Identifiant unique pour la tâche de keycap à récupérer.

Retours

La réponse contient l'objet de la tâche de keycap. La forme dépend de l'étape demandée.

Requête

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

Réponse Prototype

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

Réponse Construction

{
  "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

Supprimer une Tâche de Keycap

Annuler une tâche de keycap. Si la tâche est encore PENDING, les crédits consommés lors de la création sont remboursés. Les tâches qui sont déjà IN_PROGRESS sont annulées sans remboursement (le travailleur peut déjà être en train de consommer des ressources). Les tâches qui ont déjà atteint un état terminal (SUCCEEDED, FAILED, CANCELED) ne peuvent pas être annulées.

Le chemin URL doit correspondre à l'étape de la tâche — DELETE sur /prototype/:buildId renvoie 404.

Paramètres de Chemin

  • Name
    id
    Type
    path
    Description

    Identifiant unique pour la tâche de keycap à annuler.

Retours

Retourne 204 No Content en cas de succès avec un corps vide.

Modes d'Échec

  • Name
    400 - Bad Request
    Description

    La tâche est déjà dans un état terminal et ne peut pas être annulée.

  • Name
    404 - Not Found
    Description

    La tâche n'existe pas, appartient à un autre utilisateur, ou son étape ne correspond pas au chemin URL.

  • Name
    500 - Internal Server Error
    Description

    Une erreur inattendue côté serveur s'est produite lors de l'annulation. La tâche peut ou non avoir été annulée — relisez-la pour confirmer avant de réessayer.

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

Diffuser une tâche Keycap

Diffusez des mises à jour en temps réel pour une tâche keycap via Server-Sent Events (SSE). Le chemin URL doit correspondre à l'étape de la tâche — ouvrir un flux à /prototype/:buildId/stream émet une seule charge utile event: error avec status_code: 404 et ferme le flux.

Paramètres

  • Name
    id
    Type
    path
    Description

    Identifiant unique pour la tâche keycap à diffuser.

Retours

Retourne un flux d'objets de tâche Keycap Prototype ou Keycap Build en tant que Server-Sent Events. Pour les tâches PENDING ou IN_PROGRESS, le flux de réponse inclura uniquement les champs nécessaires progress et status.

Requête

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

Flux de Réponse

// 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.
// For PENDING or IN_PROGRESS tasks, the response stream will not include all fields.
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)

Lister les tâches Keycap

Récupérez une liste paginée de vos tâches keycap pour une seule étape. Le chemin URL sélectionne l'étape — /prototype renvoie les tâches de prototype ; /build renvoie les tâches de construction. Les tâches de l'autre étape ne sont pas incluses dans l'une ou l'autre réponse.

Paramètres de chemin

  • Name
    stage
    Type
    path
    Requis
    Description

    Soit prototype soit build. La collection renvoie uniquement les tâches dont l'étape correspond à l'URL — récupérer /prototype ne renvoie jamais de tâches de construction et vice versa.

Paramètres de requête

  • Name
    page_num
    Type
    integer
    défaut 1
    Description

    Numéro de page pour la pagination.

  • Name
    page_size
    Type
    integer
    défaut 10
    Description

    Limite de taille de page. Le maximum autorisé est de 100 éléments.

  • Name
    sort_by
    Type
    string
    défaut -created_at
    Description

    Champ par lequel trier. Valeurs disponibles :

    • +created_at: Trier par heure de création par ordre croissant.
    • -created_at: Trier par heure de création par ordre décroissant.

Retours

Renvoie une liste paginée de l'objet tâche par étape — soit l'objet tâche de prototype keycap lors de la liste /prototype ou l'objet tâche de construction keycap lors de la liste /build.

Requête

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

Réponse (Lister les tâches de prototype)

[
  {
    "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'objet Tâche Prototype de Keycap

L'objet Tâche Prototype de Keycap est une unité de travail que Meshy suit pour générer une image de conception de keycap finie à partir d'une photo source. La sortie de cette étape est enchaînée dans l'étape de construction via input_task_id plus candidate_id.

Propriétés

  • Name
    id
    Type
    string
    Description

    Identifiant unique pour la tâche. Bien que nous utilisions un UUID triable par k pour les identifiants de tâche comme détail d'implémentation, vous ne devez pas faire d'hypothèses sur le format de l'id.

  • Name
    type
    Type
    string
    Description

    Type de la tâche. La valeur est creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    Le nom de la tâche fourni lors de la création de la tâche. Chaîne vide si aucun nom n'a été fourni.

  • Name
    status
    Type
    string
    Description

    Statut de la tâche. Les valeurs possibles sont PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progression de la tâche. Si la tâche n'est pas encore commencée, cette propriété sera 0. Une fois la tâche réussie, cela deviendra 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Horodatage de la création de la tâche, en millisecondes.

  • Name
    started_at
    Type
    timestamp
    Description

    Horodatage du début de la tâche, en millisecondes. Si la tâche n'est pas encore commencée, cette propriété sera 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Horodatage de la fin de la tâche, en millisecondes. Si la tâche n'est pas encore terminée, cette propriété sera 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Horodatage de l'expiration du résultat de la tâche, en millisecondes.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Le nombre de tâches précédentes.

  • Name
    task_error
    Type
    object
    Description

    Détails des erreurs pour les tâches échouées. Voir Erreurs pour la référence complète de l'objet task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Le nombre de crédits consommés par cette tâche. Une tâche qui atteint SUCCEEDED est facturée du montant total pour son étape. Une tâche qui n'est jamais créée (un 4xx au moment de la demande, y compris un rejet de modération) n'est pas facturée du tout. Une tâche qui atteint FAILED retourne 0 — le montant est remboursé, y compris un blocage de modération asynchrone. L'annulation via DELETE est remboursée uniquement tant que la tâche est encore PENDING; une tâche déjà IN_PROGRESS reste facturée, car le travail a été effectué.

  • Name
    image_urls
    Type
    array of strings
    Description

    URL téléchargeable du rendu de conception de keycap fini — à quoi ressemble le candidat en tant que keycap fini. Contient une seule entrée; image_urls[i] correspond à candidate_ids[i]. Vide jusqu'à ce que la tâche atteigne SUCCEEDED. L'URL est uniquement pour l'affichage; le point de terminaison de construction consomme candidate_ids, pas ces URL. Même cycle de vie d'URL que model_urls: signé, sans en-tête Authorization, valide jusqu'à expires_at, et stable lorsque la tâche est relue.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Identifiants de candidats opaques, parallèles à image_urls. Passez l'entrée correspondant à votre conception choisie comme candidate_id de la demande de construction. Ne faites aucune hypothèse sur le format de ces identifiants.

Exemple d'Objet Tâche Prototype de Keycap

{
  "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'objet Tâche de Construction de Keycap

L'objet Tâche de Construction de Keycap est une unité de travail que Meshy suit pour générer le keycap 3D texturé final à partir d'une tâche prototype réussie et d'un candidat choisi. Une seule construction exécute le pipeline complet — génération de modèle blanc, placement et découpe automatiques, coloration, assemblage et exportation.

Propriétés

  • Name
    id
    Type
    string
    Description

    Identifiant unique pour la tâche.

  • Name
    type
    Type
    string
    Description

    Type de la tâche. La valeur est creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    Le nom de la tâche fourni lors de la création de la tâche. Chaîne vide si aucun nom n'a été fourni.

  • Name
    status
    Type
    string
    Description

    Statut de la tâche. Les valeurs possibles sont l'une de PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Avancement de la tâche. Si la tâche n'est pas encore commencée, cette propriété sera 0. Une fois la tâche réussie, cela deviendra 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Horodatage de la création de la tâche, en millisecondes.

  • Name
    started_at
    Type
    timestamp
    Description

    Horodatage du début de la tâche, en millisecondes.

  • Name
    finished_at
    Type
    timestamp
    Description

    Horodatage de la fin de la tâche, en millisecondes.

  • Name
    expires_at
    Type
    timestamp
    Description

    Horodatage de l'expiration du résultat de la tâche, en millisecondes.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Le nombre de tâches précédentes. Significatif uniquement lorsque le statut est PENDING.

  • Name
    task_error
    Type
    object
    Description

    Détails des erreurs pour les tâches échouées. Voir Erreurs pour la référence complète de l'objet task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Le nombre de crédits consommés par cette tâche. Une tâche qui atteint SUCCEEDED est facturée du montant total pour son étape. Une tâche qui n'est jamais créée (un 4xx au moment de la demande, y compris un rejet de modération) n'est pas facturée du tout. Une tâche qui atteint FAILED retourne 0 — la charge est remboursée, y compris un blocage de modération asynchrone. L'annulation via DELETE rembourse uniquement tant que la tâche est encore PENDING; une tâche déjà IN_PROGRESS reste facturée, car le travail a été dépensé.

  • Name
    model_urls
    Type
    object
    Description

    URLs téléchargeables pour les artefacts de modèle générés. Les deux, le GLB et le bundle OBJ, sont exportés à l'échelle réelle en millimètres, Y-up, avec l'avant du keycap face au +Z. Les maillages sont nommés keycap-head et keycap-base; lorsque la base revient à un remplissage de motif, un troisième maillage keycap-base-interior est également présent pour la cavité de la tige. Ne supposez pas exactement deux maillages.

    Ce sont des URLs signées : récupérez-les sans en-tête Authorization. Elles restent valides jusqu'à expires_at, qui est 3 jours après finished_at, et relire la tâche dans cette fenêtre retourne l'URL identique plutôt qu'une nouvelle signée. Téléchargez et stockez les fichiers vous-même avant cela — il n'y a aucun moyen de rafraîchir un lien expiré.

    • Name
      glb
      Type
      string
      Description

      URL téléchargeable vers le model.glb texturé final.

    • Name
      obj_zip
      Type
      string
      Description

      URL téléchargeable vers un bundle zip contenant model.obj, model.mtl, et les PNGs de texture que son MTL référence réellement. Une base de couleur unie expédie uniquement keycap-head.png; une base à motifs expédie également keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    URLs téléchargeables pour les images de processus intermédiaires, indexées par type. Même cycle de vie d'URL que model_urls: signées, sans en-tête Authorization, valides jusqu'à expires_at, et stables lorsque la tâche est relue. Types actuellement émis :

    • head_design — l'image de conception du candidat choisi que la construction a consommée (toujours présente).
    • composite — le rendu d'affichage du keycap fini du candidat choisi (présent lorsque disponible).
    • base_canvas — la toile de base du keycap peinte (présente lorsque disponible).

    Considérez l'ensemble des clés comme ouvert ; de nouveaux types peuvent être ajoutés sans changement majeur.

Exemple d'Objet Tâche de Construction de Keycap

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

Exemple de bout en bout

Le flux complet : créer un prototype à partir d'une photo, le sonder jusqu'à SUCCEEDED, choisir un candidat parmi candidate_ids, créer une construction avec ce candidat, sonder la construction jusqu'à SUCCEEDED, puis télécharger le GLB et le paquet OBJ depuis model_urls.

L'exemple choisit le premier candidat de manière programmatique. Dans une véritable intégration, vous afficheriez l'entrée image_urls à l'utilisateur final et le laisseriez choisir ; l'index choisi correspond 1:1 à candidate_ids.

Flux complet

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"