Creative Lab — Keycap API

Convierte una foto fuente en una tecla mecánica personalizada a todo color en dos etapas: prototipo genera un render de diseño de "tecla terminada" a partir de tu foto de entrada. Una vez que hayas confirmado ese render, construcción lo convierte en un modelo 3D texturizado de tecla en una sola ejecución: generación de modelo blanco, asiento y corte automáticos en una pose predeterminada calibrada, coloración de modelo completo y ensamblaje final, todo ocurre dentro de una sola tarea de construcción. Las dos etapas están vinculadas a través de input_task_id más candidate_id.

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

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

Crear una Tarea de Prototipo de Tecla

Genera un render de diseño de tecla terminado a partir de la foto fuente. El resultado de la tarea lleva un array image_urls (el render de visualización de la tecla terminada) y un array paralelo candidate_ids; ambos contienen una sola entrada. Llama a este endpoint nuevamente para otro render si el resultado no es lo que deseas — cada llamada se factura por separado. Pasa el candidate_id junto con el ID de la tarea de prototipo al endpoint de construcción. Consulta El Objeto de Tarea de Prototipo de Tecla para la forma de la respuesta.

Parámetros

  • Name
    image_url
    Type
    string
    Requerido
    Description

    Foto fuente para que Meshy la convierta en imágenes de diseño de tecla. Actualmente soportamos los formatos .jpg, .jpeg, .png y .webp.

    El formato se detecta decodificando los datos de la imagen, no a partir de la extensión del archivo de la URL — una URL sin extensión, o una que redirige, funciona siempre que los bytes se decodifiquen a un formato compatible. Se siguen las redirecciones HTTP. La orientación EXIF se normaliza, por lo que una foto de teléfono rotada se usa tal como se ve.

    Límites: al menos 32 píxeles en cada lado, como máximo 178,956,970 píxeles en total, y como máximo 20,000,000 bytes una vez descargada. Para un Data URI, el límite se aplica a los bytes decodificados, por lo que el archivo fuente en sí puede tener hasta ese tamaño — es el texto base64 el que es aproximadamente un tercio más grande, lo que importa para el cuerpo de tu solicitud, no para este límite. Un Data URI debe declarar un tipo de contenido image/* y ;base64.

    Hay dos formas de proporcionar la imagen:

    • URL accesible públicamente: Una URL que es accesible desde internet público.
    • Data URI: Un Data URI codificado en base64 de la imagen. Ejemplo de un Data URI: data:image/jpeg;base64,<tus datos de imagen codificados en base64>.
  • Name
    name
    Type
    string
    Description

    Nombre de tarea opcional para propósitos de visualización. Máximo 100 caracteres.

  • Name
    remove_background
    Type
    boolean
    predeterminado false
    Description

    Cuando se establece en true, el render de visualización devuelto en image_urls es un PNG RGBA transparente con el fondo eliminado, para que puedas componerlo sobre cualquier fondo.

    Esto se aplica solo al render de visualización. El candidato que consume el endpoint de construcción no se ve afectado, por lo que el resultado 3D es idéntico de cualquier manera.

Retornos

La propiedad result de la respuesta contiene el id de la tarea de prototipo de tecla recién creada. Consulta el endpoint Obtener una Tarea o suscríbete al stream hasta que la tarea alcance SUCCEEDED, luego toma la entrada de candidate_ids y pásala, junto con el ID de la tarea, al endpoint de construcción.

Modos de Fallo

  • Name
    400 - Bad Request
    Description

    La solicitud fue inaceptable. Causas comunes:

    • Parámetro faltante: image_url es requerido.
    • Formato de imagen no válido: El image_url proporcionado no es un formato compatible (.jpg, .jpeg, .png, .webp).
    • Dimensiones de imagen fuera de rango: La imagen es demasiado pequeña, excede el tamaño máximo de archivo o excede el conteo máximo de píxeles.
    • URL inalcanzable: El image_url no se pudo descargar (404 o timeout).
    • Data URI no válido: La cadena base64 está mal formada.
    • Contenido marcado: La imagen de entrada fue marcada por la moderation NSFW.
  • Name
    401 - Unauthorized
    Description

    La autenticación falló. Por favor verifica tu clave de API.

  • Name
    402 - Payment Required
    Description

    La cuenta está en el plan gratuito (se requiere un plan de pago para crear tareas) o no tiene suficientes créditos.

  • Name
    403 - Forbidden
    Description

    La imagen de entrada fue marcada por la moderation de propiedad intelectual.

  • Name
    429 - Too Many Requests
    Description

    Has excedido tu límite de tasa.

  • Name
    500 - Internal Server Error
    Description

    Ocurrió un error inesperado del lado del servidor — por ejemplo, el servicio de moderation de contenido no estaba disponible, falló la preparación de la imagen de entrada, o no se pudo crear la tarea. No se crea ninguna tarea en este caso, por lo que reintentar es seguro.

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

Crear una Tarea de Construcción de Keycap

Genera el modelo 3D final con textura del keycap a partir de una tarea de prototipo exitosa y uno de sus candidatos. Una sola tarea de construcción ejecuta todo el proceso de principio a fin: generación del modelo blanco a partir del diseño elegido, ajuste automático y corte en la base del keycap usando una pose predeterminada calibrada (no se necesita ajuste interactivo), coloración del modelo completo, y ensamblaje y exportación final. Una construcción típicamente toma 3–7 minutos, hacia el extremo superior cuando varias construcciones se ejecutan simultáneamente. Consulta El Objeto de Tarea de Construcción de Keycap para la forma de la respuesta.

Parámetros

  • Name
    input_task_id
    Type
    string
    Requerido
    Description

    El ID de la tarea de un prototipo creado a través de este mismo endpoint de OpenAPI. El prototipo debe haber sido creado por la misma cuenta de Meshy, debe haber alcanzado SUCCEEDED, y debe haber producido al menos un candidato.

    Las tareas de prototipo creadas a través de la aplicación web no son aceptadas — el endpoint de construcción solo acepta tareas de prototipo producidas por POST /openapi/creative-lab/keycap/v1/prototype y rechaza cualquier otra fuente con 404.

  • Name
    candidate_id
    Type
    string
    Requerido
    Description

    El candidato a construir, tomado del array candidate_ids de la tarea de prototipo exitosa. Debe pertenecer a esa tarea; cualquier otro valor es rechazado con 400.

  • Name
    name
    Type
    string
    Description

    Nombre de tarea opcional para propósitos de visualización. Máximo 100 caracteres.

options

Ajuste opcional de geometría. Cada campo tiene un valor predeterminado calibrado — envía solo los que deseas anular.

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

    La base del keycap sobre la cual construir. Actualmente el único valor disponible es cherry-mx-1x1-r1 — un keycap estándar de perfil Cherry MX 1u. Se planean 3–5 tamaños estándar principales adicionales; los tamaños personalizados no son compatibles.

  • Name
    head_size_mm
    Type
    number
    predeterminado 23
    Description

    Tamaño objetivo de la cabeza esculpida, en milímetros: su dimensión más larga se escala a este valor. Rango: [10, 40]. Los valores por encima de aproximadamente 32.9 pueden ser reducidos para que la cabeza aún se ajuste al límite de la huella protectora de la base, por lo que la dimensión más larga entregada puede ser menor a la solicitada. El valor aplicado no se refleja en el objeto de la tarea hoy en día — si necesitas confirmar el tamaño que realmente recibiste, mide la caja delimitadora de la malla keycap-head en el modelo descargado.

  • Name
    vertical_offset_mm
    Type
    number
    predeterminado 0
    Description

    Desplazamiento vertical aplicado a la cabeza antes de que se asiente en la base, en milímetros. Rango: [-5, 5].

Retornos

La propiedad result de la respuesta contiene el id de la tarea de construcción de keycap recién creada. Consulta el endpoint Obtener una Tarea o suscríbete al stream hasta que la tarea alcance SUCCEEDED, luego descarga los artefactos de model_urls.glb y model_urls.obj_zip.

Modos de Fallo

  • Name
    400 - Bad Request
    Description

    La solicitud no fue aceptable. Causas comunes:

    • Parámetro faltante: input_task_id y candidate_id son requeridos.
    • UUID inválido: El input_task_id no es un UUID válido.
    • Padre no exitoso: La tarea de prototipo referenciada aún no ha alcanzado SUCCEEDED.
    • Sin candidatos: La tarea de prototipo tuvo éxito pero no produjo candidatos.
    • Candidato desconocido: candidate_id no es uno de los candidatos de la tarea de entrada.
    • Opciones fuera de rango: Uno de los campos options cayó fuera de su rango permitido o conjunto de enumeración.
  • Name
    401 - Unauthorized
    Description

    La autenticación falló. Por favor verifica tu clave de API.

  • Name
    402 - Payment Required
    Description

    La cuenta está en el plan gratuito (se requiere un plan de pago para crear tareas) o no tiene suficientes créditos.

  • Name
    404 - Not Found
    Description

    La tarea de prototipo referenciada no existe, pertenece a un usuario diferente, o fue creada a través de la aplicación web (solo las tareas de prototipo en modo API se encadenan en la construcción).

  • Name
    429 - Too Many Requests
    Description

    Has excedido tu límite de tasa.

  • Name
    500 - Internal Server Error
    Description

    Ocurrió un error inesperado del lado del servidor — por ejemplo, el servicio de moderación de contenido no estaba disponible, la puesta en escena de la imagen de entrada falló, o la tarea no pudo ser creada. No se crea ninguna tarea en este caso, por lo que volver a intentarlo es seguro.

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

Recuperar una Tarea de Keycap

Recupera una tarea de prototipo o construcción dada una id de tarea válida. La ruta de la URL debe coincidir con la etapa de la tarea: una tarea de construcción obtenida a través de /prototype/:id devuelve 404, y viceversa.

Consulta El Objeto de Tarea de Prototipo de Keycap y El Objeto de Tarea de Construcción de Keycap para las formas de respuesta.

Parámetros

  • Name
    id
    Type
    path
    Description

    Identificador único para la tarea de keycap a recuperar.

Devuelve

La respuesta contiene el objeto de tarea de keycap. La forma depende de qué etapa fue solicitada.

Solicitud

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

Respuesta de Prototipo

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

Respuesta de Construcción

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

Eliminar una Tarea de Keycap

Cancela una tarea de keycap. Si la tarea aún está PENDING, los créditos consumidos al momento de la creación son reembolsados. Las tareas que ya están IN_PROGRESS se cancelan sin reembolso (el trabajador puede ya estar consumiendo recursos). Las tareas que ya han alcanzado un estado terminal (SUCCEEDED, FAILED, CANCELED) no pueden ser canceladas.

La ruta URL debe coincidir con la etapa de la tarea — DELETE en /prototype/:buildId devuelve 404.

Parámetros de Ruta

  • Name
    id
    Type
    path
    Description

    Identificador único para la tarea de keycap a cancelar.

Retornos

Devuelve 204 No Content en caso de éxito con un cuerpo vacío.

Modos de Fallo

  • Name
    400 - Bad Request
    Description

    La tarea ya está en un estado terminal y no puede ser cancelada.

  • Name
    404 - Not Found
    Description

    La tarea no existe, pertenece a un usuario diferente, o su etapa no coincide con la ruta URL.

  • Name
    500 - Internal Server Error
    Description

    Ocurrió un error inesperado del lado del servidor al cancelar. La tarea puede o no haber sido cancelada — vuelva a leerla para confirmar antes de reintentar.

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

Transmitir una Tarea de Keycap

Transmite actualizaciones en tiempo real para una tarea de keycap a través de Server-Sent Events (SSE). La ruta de la URL debe coincidir con la etapa de la tarea: abrir una transmisión en /prototype/:buildId/stream emite un único event: error payload con status_code: 404 y cierra la transmisión.

Parámetros

  • Name
    id
    Type
    path
    Description

    Identificador único para la tarea de keycap a transmitir.

Retornos

Devuelve una transmisión de objetos de tarea de Prototipo de Keycap o Construcción de Keycap como Server-Sent Events. Para tareas PENDING o IN_PROGRESS, la transmisión de respuesta solo incluirá los campos necesarios de progress y status.

Solicitud

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.
// 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)

Listar Tareas de Keycap

Recupera una lista paginada de tus tareas de keycap para una sola etapa. La ruta URL selecciona la etapa — /prototype devuelve tareas de prototipo; /build devuelve tareas de construcción. Las tareas de la otra etapa no están incluidas en ninguna de las respuestas.

Parámetros de Ruta

  • Name
    stage
    Type
    path
    Requerido
    Description

    Ya sea prototype o build. La colección devuelve solo tareas cuya etapa coincide con la URL — al buscar /prototype nunca se devuelven tareas de construcción y viceversa.

Parámetros de Consulta

  • Name
    page_num
    Type
    integer
    predeterminado 1
    Description

    Número de página para la paginación.

  • Name
    page_size
    Type
    integer
    predeterminado 10
    Description

    Límite de tamaño de página. El máximo permitido es de 100 elementos.

  • Name
    sort_by
    Type
    string
    predeterminado -created_at
    Description

    Campo para ordenar. Valores disponibles:

    • +created_at: Ordenar por tiempo de creación en orden ascendente.
    • -created_at: Ordenar por tiempo de creación en orden descendente.

Retornos

Devuelve una lista paginada del objeto de tarea por etapa — ya sea el objeto de tarea de prototipo de keycap al listar /prototype o el objeto de tarea de construcción de keycap al listar /build.

Solicitud

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

Respuesta (Listar Tareas de Prototipo)

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

El Objeto de Tarea de Prototipo de Keycap

El objeto de Tarea de Prototipo de Keycap es una unidad de trabajo que Meshy rastrea para generar una imagen de diseño de keycap terminado a partir de una foto fuente. La salida de esta etapa se encadena en la etapa de construcción a través de input_task_id más candidate_id.

Propiedades

  • Name
    id
    Type
    string
    Description

    Identificador único para la tarea. Aunque usamos un UUID ordenable por clave para los ids de tarea como detalle de implementación, no debes hacer ninguna suposición sobre el formato del id.

  • Name
    type
    Type
    string
    Description

    Tipo de la tarea. El valor es creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    El nombre de la tarea proporcionado cuando se creó la tarea. Cadena vacía si no se proporcionó un nombre.

  • Name
    status
    Type
    string
    Description

    Estado de la tarea. Los valores posibles son uno de PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progreso de la tarea. Si la tarea aún no ha comenzado, esta propiedad será 0. Una vez que la tarea haya tenido éxito, esto se convertirá en 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando se creó la tarea, en milisegundos.

  • Name
    started_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando se inició la tarea, en milisegundos. Si la tarea aún no ha comenzado, esta propiedad será 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando se terminó la tarea, en milisegundos. Si la tarea aún no ha terminado, esta propiedad será 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando expira el resultado de la tarea, en milisegundos.

  • Name
    preceding_tasks
    Type
    integer
    Description

    El conteo de tareas precedentes.

  • Name
    task_error
    Type
    object
    Description

    Detalles de error para tareas fallidas. Consulta Errores para la referencia completa del objeto task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    El número de créditos consumidos por esta tarea. Una tarea que alcanza SUCCEEDED se cobra el monto total por su etapa. Una tarea que nunca se crea (un 4xx en el momento de la solicitud, incluida una moderación rechazada) no se cobra en absoluto. Una tarea que alcanza FAILED devuelve 0 — el cargo es reembolsado, incluyendo un bloqueo de moderación asincrónico. Cancelar a través de DELETE solo reembolsa mientras la tarea aún está PENDING; una tarea ya IN_PROGRESS permanece cobrada, porque el trabajo ha sido gastado.

  • Name
    image_urls
    Type
    array of strings
    Description

    URL descargable del render del diseño de keycap terminado — cómo se ve el candidato como un keycap terminado. Contiene una sola entrada; image_urls[i] corresponde a candidate_ids[i]. Vacío hasta que la tarea alcanza SUCCEEDED. La URL es solo para visualización; el endpoint de construcción consume candidate_ids, no estas URLs. Mismo ciclo de vida de URL que model_urls: firmada, sin encabezado Authorization, válida hasta expires_at, y estable cuando se vuelve a leer la tarea.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Identificadores de candidatos opacos, paralelos a image_urls. Pasa la entrada que coincide con tu diseño elegido como candidate_id de la solicitud de construcción. No hagas ninguna suposición sobre el formato de estos 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"
  ]
}

El Objeto de Tarea de Construcción de Keycap

El objeto de Tarea de Construcción de Keycap es una unidad de trabajo que Meshy sigue para generar el keycap 3D texturizado final a partir de una tarea de prototipo exitosa y un candidato elegido. Una sola construcción ejecuta toda la canalización: generación de modelo blanco, asiento y corte automáticos, coloración, ensamblaje y exportación.

Propiedades

  • Name
    id
    Type
    string
    Description

    Identificador único para la tarea.

  • Name
    type
    Type
    string
    Description

    Tipo de la tarea. El valor es creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    El nombre de la tarea proporcionado cuando se creó la tarea. Cadena vacía si no se proporcionó un nombre.

  • Name
    status
    Type
    string
    Description

    Estado de la tarea. Los valores posibles son uno de PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progreso de la tarea. Si la tarea aún no ha comenzado, esta propiedad será 0. Una vez que la tarea haya tenido éxito, esto se convertirá en 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando se creó la tarea, en milisegundos.

  • Name
    started_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando se inició la tarea, en milisegundos.

  • Name
    finished_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando se terminó la tarea, en milisegundos.

  • Name
    expires_at
    Type
    timestamp
    Description

    Marca de tiempo de cuando expira el resultado de la tarea, en milisegundos.

  • Name
    preceding_tasks
    Type
    integer
    Description

    El conteo de tareas precedentes. Significativo solo cuando el estado es PENDING.

  • Name
    task_error
    Type
    object
    Description

    Detalles del error para tareas fallidas. Consulte Errores para la referencia completa del objeto task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    El número de créditos consumidos por esta tarea. Una tarea que alcanza SUCCEEDED se cobra el monto total por su etapa. Una tarea que nunca se crea (un 4xx en el momento de la solicitud, incluida una moderación rechazada) no se cobra en absoluto. Una tarea que alcanza FAILED devuelve 0 — el cargo es reembolsado, incluida una moderación asincrónica bloqueada. Cancelar a través de DELETE solo reembolsa mientras la tarea aún está PENDING; una tarea ya IN_PROGRESS permanece cobrada, porque el trabajo ha sido gastado.

  • Name
    model_urls
    Type
    object
    Description

    URLs descargables para los artefactos del modelo generado. Tanto el GLB como el paquete OBJ se exportan a escala milimétrica del mundo real, Y-arriba, con el frente del keycap mirando hacia +Z. Las mallas se nombran keycap-head y keycap-base; cuando la base recurre a un relleno de patrón, también está presente una tercera malla keycap-base-interior para la cavidad del vástago. No asuma exactamente dos mallas.

    Estas son URLs firmadas: recupérelas sin un encabezado de Authorization. Permanecen válidas hasta expires_at, que es 3 días después de finished_at, y volver a leer la tarea dentro de esa ventana devuelve la URL idéntica en lugar de una recién firmada. Descargue y almacene los archivos usted mismo antes de entonces — no hay forma de actualizar un enlace expirado.

    • Name
      glb
      Type
      string
      Description

      URL descargable al model.glb texturizado final.

    • Name
      obj_zip
      Type
      string
      Description

      URL descargable a un paquete zip que contiene model.obj, model.mtl, y los PNGs de textura que su MTL realmente referencia. Una base de color sólido solo envía keycap-head.png; una base con patrón también envía keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    URLs descargables para imágenes de proceso intermedio, clasificadas por tipo. Mismo ciclo de vida de URL que model_urls: firmadas, sin encabezado de Authorization, válidas hasta expires_at, y estables cuando se vuelve a leer la tarea. Tipos actualmente emitidos:

    • head_design — la imagen de diseño del candidato elegido que la construcción consumió (siempre presente).
    • composite — la representación de visualización del keycap terminado del candidato elegido (presente cuando está disponible).
    • base_canvas — el lienzo de base del keycap pintado (presente cuando está disponible).

    Trate el conjunto de claves como abierto; se pueden agregar nuevos tipos sin un cambio disruptivo.

Ejemplo de Objeto de Tarea de Construcción 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=***"
  }
}

Ejemplo de principio a fin

El flujo completo: crear un prototipo a partir de una foto, sondearlo hasta SUCCEEDED, elegir un candidato de candidate_ids, crear una construcción con ese candidato, sondear la construcción hasta SUCCEEDED, luego descargar el GLB y el paquete OBJ de model_urls.

El ejemplo elige el primer candidato programáticamente. En una integración real, mostrarías la entrada de image_urls al usuario final y dejarías que ellos elijan; el índice elegido se mapea 1:1 con candidate_ids.

Flujo completo

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"