Creative Lab — Keycap API

Transforme uma foto de origem em uma tecla mecânica personalizada e colorida em duas etapas: protótipo gera um render de design de "tecla finalizada" a partir da sua foto de entrada. Uma vez que você tenha confirmado esse render, construir transforma-o em um modelo 3D de tecla texturizada em uma única execução — geração de modelo branco, posicionamento e corte automáticos em uma pose padrão calibrada, coloração do modelo completo e montagem final acontecem todos dentro de uma única tarefa de construção. As duas etapas são vinculadas via input_task_id mais candidate_id.

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

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

Criar uma Tarefa de Protótipo de Keycap

Gere um render de design de keycap finalizado a partir da foto de origem. O resultado da tarefa carrega um array image_urls (o render de exibição do keycap finalizado) e um array paralelo candidate_ids; ambos contêm uma única entrada. Chame este endpoint novamente para outro render se o resultado não for o que você deseja — cada chamada é cobrada separadamente. Passe o candidate_id junto com o ID da tarefa de protótipo para o endpoint de construção. Consulte O Objeto de Tarefa de Protótipo de Keycap para o formato da resposta.

Parâmetros

  • Name
    image_url
    Type
    string
    Obrigatório
    Description

    Foto de origem para a Meshy transformar em imagens de design de keycap. Atualmente, suportamos os formatos .jpg, .jpeg, .png e .webp.

    O formato é detectado decodificando os dados da imagem, não pela extensão do arquivo da URL — uma URL sem extensão, ou que redireciona, funciona desde que os bytes sejam decodificados para um formato suportado. Redirecionamentos HTTP são seguidos. A orientação EXIF é normalizada, então uma foto de telefone rotacionada é usada da forma como parece.

    Limites: pelo menos 32 pixels de cada lado, no máximo 178,956,970 pixels no total, e no máximo 20,000,000 bytes uma vez baixado. Para um Data URI, o limite se aplica aos bytes decodificados, então o arquivo de origem em si pode ter até esse tamanho — é o texto base64 que é cerca de um terço maior, o que importa para o corpo da sua solicitação, não para este limite. Um Data URI deve declarar um tipo de conteúdo image/* e ;base64.

    Existem duas maneiras de fornecer a imagem:

    • URL publicamente acessível: Uma URL acessível da internet pública.
    • Data URI: Um Data URI codificado em base64 da imagem. Exemplo de um Data URI: data:image/jpeg;base64,<seus dados de imagem codificados em base64>.
  • Name
    name
    Type
    string
    Description

    Nome de tarefa opcional para fins de exibição. Máximo de 100 caracteres.

  • Name
    remove_background
    Type
    boolean
    padrão false
    Description

    Quando definido como true, o render de exibição retornado em image_urls é um PNG RGBA transparente com o fundo removido, para que você possa compô-lo em qualquer fundo.

    Isso se aplica apenas ao render de exibição. O candidato que o endpoint de construção consome não é afetado, então o resultado 3D é idêntico de qualquer forma.

Retornos

A propriedade result da resposta contém o id da tarefa da nova tarefa de protótipo de keycap criada. Consulte o endpoint Obter uma Tarefa ou assine o stream até que a tarefa atinja SUCCEEDED, então pegue a entrada de candidate_ids e passe-a, junto com o ID da tarefa, para o endpoint de construção.

Modos de Falha

  • Name
    400 - Bad Request
    Description

    A solicitação foi inaceitável. Causas comuns:

    • Parâmetro ausente: image_url é obrigatório.
    • Formato de imagem inválido: O image_url fornecido não é um formato suportado (.jpg, .jpeg, .png, .webp).
    • Dimensões da imagem fora do intervalo: A imagem é muito pequena, excede o tamanho máximo do arquivo ou excede a contagem máxima de pixels.
    • URL inacessível: O image_url não pôde ser baixado (404 ou timeout).
    • Data URI inválido: A string base64 está malformada.
    • Conteúdo sinalizado: A imagem de entrada foi sinalizada pela moderação NSFW.
  • Name
    401 - Unauthorized
    Description

    A autenticação falhou. Por favor, verifique sua chave de API.

  • Name
    402 - Payment Required
    Description

    A conta está no plano gratuito (um plano pago é necessário para criar tarefas) ou não possui créditos suficientes.

  • Name
    403 - Forbidden
    Description

    A imagem de entrada foi sinalizada pela moderação de propriedade intelectual.

  • Name
    429 - Too Many Requests
    Description

    Você excedeu seu limite de taxa.

  • Name
    500 - Internal Server Error
    Description

    Ocorreu um erro inesperado no servidor — por exemplo, o serviço de moderação de conteúdo estava indisponível, a preparação da imagem de entrada falhou ou a tarefa não pôde ser criada. Nenhuma tarefa é criada neste caso, então tentar novamente é 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

Criar uma Tarefa de Construção de Keycap

Gere o modelo 3D final texturizado de keycap a partir de uma tarefa de protótipo bem-sucedida e um de seus candidatos. Uma única tarefa de construção executa todo o pipeline de ponta a ponta — geração de modelo branco a partir do design escolhido, posicionamento e corte automáticos na base do keycap usando uma pose padrão calibrada (sem necessidade de ajuste interativo), coloração do modelo completo, e montagem e exportação finais. Uma construção geralmente leva 3–7 minutos, tendendo para o limite superior quando várias construções são executadas simultaneamente. Consulte O Objeto de Tarefa de Construção de Keycap para o formato da resposta.

Parâmetros

  • Name
    input_task_id
    Type
    string
    Obrigatório
    Description

    O ID da tarefa de um protótipo criado através deste mesmo endpoint OpenAPI. O protótipo deve ter sido criado pela mesma conta Meshy, deve ter alcançado SUCCEEDED e deve ter produzido pelo menos um candidato.

    Tarefas de protótipo criadas através do webapp não são aceitas — o endpoint de construção aceita apenas tarefas de protótipo produzidas por POST /openapi/creative-lab/keycap/v1/prototype e recusa qualquer outra fonte com 404.

  • Name
    candidate_id
    Type
    string
    Obrigatório
    Description

    O candidato a ser construído, retirado do array candidate_ids da tarefa de protótipo bem-sucedida. Deve pertencer a essa tarefa; qualquer outro valor é rejeitado com 400.

  • Name
    name
    Type
    string
    Description

    Nome opcional da tarefa para fins de exibição. Máximo de 100 caracteres.

options

Ajuste opcional de geometria. Cada campo tem um padrão calibrado — envie apenas os que você deseja substituir.

  • Name
    base_model
    Type
    string
    padrão cherry-mx-1x1-r1
    Description

    A base do keycap a ser construída. Atualmente, o único valor disponível é cherry-mx-1x1-r1 — um keycap padrão de perfil Cherry MX 1u. Estão planejados 3–5 tamanhos padrão adicionais; tamanhos personalizados não são suportados.

  • Name
    head_size_mm
    Type
    number
    padrão 23
    Description

    Tamanho alvo da cabeça esculpida, em milímetros: sua maior dimensão é escalada para este valor. Intervalo: [10, 40]. Valores acima de aproximadamente 32.9 podem ser reduzidos para que a cabeça ainda caiba no limite de proteção da base, então a maior dimensão entregue pode ser menor do que a solicitada. O valor aplicado não é refletido de volta no objeto da tarefa hoje — se você precisar confirmar o tamanho que realmente recebeu, meça a caixa delimitadora da malha keycap-head no modelo baixado.

  • Name
    vertical_offset_mm
    Type
    number
    padrão 0
    Description

    Deslocamento vertical aplicado à cabeça antes de ser assentada na base, em milímetros. Intervalo: [-5, 5].

Retornos

A propriedade result da resposta contém o id da tarefa recém-criada de construção de keycap. Consulte o endpoint Obter uma Tarefa ou assine o stream até que a tarefa alcance SUCCEEDED, então baixe os artefatos de model_urls.glb e model_urls.obj_zip.

Modos de Falha

  • Name
    400 - Bad Request
    Description

    A solicitação foi inaceitável. Causas comuns:

    • Parâmetro ausente: input_task_id e candidate_id são obrigatórios.
    • UUID inválido: O input_task_id não é um UUID válido.
    • Pai não bem-sucedido: A tarefa de protótipo referenciada ainda não alcançou SUCCEEDED.
    • Sem candidatos: A tarefa de protótipo foi bem-sucedida, mas não produziu candidatos.
    • Candidato desconhecido: candidate_id não é um dos candidatos da tarefa de entrada.
    • Opções fora do intervalo: Um dos campos options caiu fora do intervalo permitido ou conjunto de enumeração.
  • Name
    401 - Unauthorized
    Description

    A autenticação falhou. Por favor, verifique sua chave de API.

  • Name
    402 - Payment Required
    Description

    A conta está no plano gratuito (um plano pago é necessário para criar tarefas) ou não possui créditos suficientes.

  • Name
    404 - Not Found
    Description

    A tarefa de protótipo referenciada não existe, pertence a um usuário diferente ou foi criada através do webapp (apenas tarefas de protótipo em modo API encadeiam em construção).

  • Name
    429 - Too Many Requests
    Description

    Você excedeu seu limite de taxa.

  • Name
    500 - Internal Server Error
    Description

    Ocorreu um erro inesperado no lado do servidor — por exemplo, o serviço de moderação de conteúdo estava indisponível, a preparação da imagem de entrada falhou ou a tarefa não pôde ser criada. Nenhuma tarefa é criada neste caso, então tentar novamente é 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 uma Tarefa de Keycap

Recupere uma tarefa de protótipo ou construção fornecendo um id de tarefa válido. O caminho da URL deve corresponder ao estágio da tarefa — uma tarefa de construção buscada através de /prototype/:id retorna 404, e vice-versa.

Consulte O Objeto de Tarefa de Protótipo de Keycap e O Objeto de Tarefa de Construção de Keycap para formatos de resposta.

Parâmetros

  • Name
    id
    Type
    path
    Description

    Identificador único para a tarefa de keycap a ser recuperada.

Retornos

A resposta contém o objeto da tarefa de keycap. O formato depende de qual estágio foi solicitado.

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

Excluir uma Tarefa de Keycap

Cancelar uma tarefa de keycap. Se a tarefa ainda estiver PENDING, os créditos consumidos no momento da criação são reembolsados. Tarefas que já estão IN_PROGRESS são canceladas sem reembolso (o trabalhador pode já estar consumindo recursos). Tarefas que já atingiram um estado terminal (SUCCEEDED, FAILED, CANCELED) não podem ser canceladas.

O caminho da URL deve corresponder ao estágio da tarefa — DELETE em /prototype/:buildId retorna 404.

Parâmetros de Caminho

  • Name
    id
    Type
    path
    Description

    Identificador único para a tarefa de keycap a ser cancelada.

Retornos

Retorna 204 No Content em caso de sucesso com um corpo vazio.

Modos de Falha

  • Name
    400 - Bad Request
    Description

    A tarefa já está em um estado terminal e não pode ser cancelada.

  • Name
    404 - Not Found
    Description

    A tarefa não existe, pertence a um usuário diferente ou seu estágio não corresponde ao caminho da URL.

  • Name
    500 - Internal Server Error
    Description

    Ocorreu um erro inesperado no servidor ao cancelar. A tarefa pode ou não ter sido cancelada — leia novamente para confirmar antes de tentar novamente.

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 uma Tarefa de Keycap

Transmita atualizações em tempo real para uma tarefa de keycap via Server-Sent Events (SSE). O caminho da URL deve corresponder ao estágio da tarefa — abrir uma transmissão em /prototype/:buildId/stream emite um único event: error payload com status_code: 404 e fecha a transmissão.

Parâmetros

  • Name
    id
    Type
    path
    Description

    Identificador único para a tarefa de keycap a ser transmitida.

Retornos

Retorna uma transmissão de objetos de tarefa Protótipo de Keycap ou Construção de Keycap como Server-Sent Events. Para tarefas PENDING ou IN_PROGRESS, a transmissão de resposta incluirá apenas os campos necessários progress e status.

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.
// 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 Tarefas de Keycap

Recupere uma lista paginada de suas tarefas de keycap para um único estágio. O caminho da URL seleciona o estágio — /prototype retorna tarefas de protótipo; /build retorna tarefas de construção. Tarefas do outro estágio não são incluídas em nenhuma das respostas.

Parâmetros de Caminho

  • Name
    stage
    Type
    path
    Obrigatório
    Description

    Ou prototype ou build. A coleção retorna apenas tarefas cujo estágio corresponda à URL — buscar /prototype nunca retorna tarefas de construção e vice-versa.

Parâmetros de Consulta

  • Name
    page_num
    Type
    integer
    padrão 1
    Description

    Número da página para paginação.

  • Name
    page_size
    Type
    integer
    padrão 10
    Description

    Limite de tamanho da página. O máximo permitido é 100 itens.

  • Name
    sort_by
    Type
    string
    padrão -created_at
    Description

    Campo para ordenar. Valores disponíveis:

    • +created_at: Ordenar por tempo de criação em ordem crescente.
    • -created_at: Ordenar por tempo de criação em ordem decrescente.

Retornos

Retorna uma lista paginada do objeto de tarefa por estágio — ou o objeto de tarefa de protótipo de keycap ao listar /prototype ou o objeto de tarefa de construção de keycap ao listar /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"
    ]
  }
]

O Objeto de Tarefa de Protótipo de Keycap

O objeto de Tarefa de Protótipo de Keycap é uma unidade de trabalho que a Meshy acompanha para gerar uma imagem de design de keycap finalizada a partir de uma foto de origem. A saída desta etapa é encadeada na etapa de construção via input_task_id mais candidate_id.

Propriedades

  • Name
    id
    Type
    string
    Description

    Identificador único para a tarefa. Embora usemos um UUID ordenável por k para ids de tarefa como detalhe de implementação, você não deve fazer suposições sobre o formato do id.

  • Name
    type
    Type
    string
    Description

    Tipo da tarefa. O valor é creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    O nome da tarefa fornecido quando a tarefa foi criada. String vazia se nenhum nome foi fornecido.

  • Name
    status
    Type
    string
    Description

    Status da tarefa. Os valores possíveis são um de PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progresso da tarefa. Se a tarefa ainda não foi iniciada, esta propriedade será 0. Uma vez que a tarefa tenha sido concluída com sucesso, isso se tornará 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando a tarefa foi criada, em milissegundos.

  • Name
    started_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando a tarefa foi iniciada, em milissegundos. Se a tarefa ainda não foi iniciada, esta propriedade será 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando a tarefa foi concluída, em milissegundos. Se a tarefa ainda não foi concluída, esta propriedade será 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando o resultado da tarefa expira, em milissegundos.

  • Name
    preceding_tasks
    Type
    integer
    Description

    A contagem de tarefas precedentes.

  • Name
    task_error
    Type
    object
    Description

    Detalhes de erro para tarefas falhadas. Veja Erros para a referência completa do objeto task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    O número de créditos consumidos por esta tarefa. Uma tarefa que atinge SUCCEEDED é cobrada pelo valor total de sua etapa. Uma tarefa que nunca é criada (um 4xx no momento da solicitação, incluindo uma rejeição de moderação) não é cobrada. Uma tarefa que atinge FAILED retorna 0 — o valor é reembolsado, incluindo um bloqueio de moderação assíncrono. Cancelar via DELETE reembolsa apenas enquanto a tarefa ainda está PENDING; uma tarefa já IN_PROGRESS permanece cobrada, pois o trabalho já foi realizado.

  • Name
    image_urls
    Type
    array of strings
    Description

    URL para download do render do design de keycap finalizado — como o candidato se parece como um keycap finalizado. Contém uma única entrada; image_urls[i] corresponde a candidate_ids[i]. Vazio até que a tarefa atinja SUCCEEDED. A URL é apenas para exibição; o endpoint de construção consome candidate_ids, não essas URLs. Mesmo ciclo de vida da URL que model_urls: assinada, sem cabeçalho Authorization, válida até expires_at, e estável quando a tarefa é relida.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Identificadores de candidatos opacos, paralelos a image_urls. Passe a entrada correspondente ao design escolhido como candidate_id da solicitação de construção. Não faça suposições sobre o formato desses ids.

Exemplo de Objeto de Tarefa de Protótipo 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"
  ]
}

O Objeto de Tarefa de Construção de Keycap

O objeto de Tarefa de Construção de Keycap é uma unidade de trabalho que a Meshy acompanha para gerar o keycap 3D texturizado final a partir de uma tarefa de protótipo bem-sucedida e um candidato escolhido. Uma única construção executa todo o pipeline — geração do modelo branco, ajuste e corte automáticos, coloração, montagem e exportação.

Propriedades

  • Name
    id
    Type
    string
    Description

    Identificador único para a tarefa.

  • Name
    type
    Type
    string
    Description

    Tipo da tarefa. O valor é creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    O nome da tarefa fornecido quando a tarefa foi criada. String vazia se nenhum nome foi fornecido.

  • Name
    status
    Type
    string
    Description

    Status da tarefa. Os valores possíveis são um dos PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Progresso da tarefa. Se a tarefa ainda não foi iniciada, esta propriedade será 0. Uma vez que a tarefa tenha sido concluída com sucesso, isso se tornará 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando a tarefa foi criada, em milissegundos.

  • Name
    started_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando a tarefa foi iniciada, em milissegundos.

  • Name
    finished_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando a tarefa foi concluída, em milissegundos.

  • Name
    expires_at
    Type
    timestamp
    Description

    Carimbo de data/hora de quando o resultado da tarefa expira, em milissegundos.

  • Name
    preceding_tasks
    Type
    integer
    Description

    A contagem de tarefas precedentes. Significativo apenas quando o status é PENDING.

  • Name
    task_error
    Type
    object
    Description

    Detalhes do erro para tarefas falhadas. Veja Erros para a referência completa do objeto task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    O número de créditos consumidos por esta tarefa. Uma tarefa que atinge SUCCEEDED é cobrada pelo valor total de sua etapa. Uma tarefa que nunca é criada (um 4xx no momento da solicitação, incluindo uma rejeição de moderação) não é cobrada. Uma tarefa que atinge FAILED retorna 0 — a cobrança é reembolsada, incluindo um bloqueio de moderação assíncrono. Cancelar via DELETE reembolsa apenas enquanto a tarefa ainda está PENDING; uma tarefa já IN_PROGRESS permanece cobrada, pois o trabalho já foi gasto.

  • Name
    model_urls
    Type
    object
    Description

    URLs para download dos artefatos do modelo gerado. Tanto o GLB quanto o pacote OBJ são exportados em escala real em milímetros, Y para cima, com a frente do keycap voltada para +Z. As malhas são nomeadas keycap-head e keycap-base; quando a base recai para um preenchimento padrão, uma terceira malha keycap-base-interior também está presente para a cavidade do caule. Não assuma exatamente duas malhas.

    Estas são URLs assinadas: busque-as sem um cabeçalho Authorization. Elas permanecem válidas até expires_at, que é 3 dias após finished_at, e reler a tarefa dentro desse período retorna a URL idêntica em vez de uma recém-assinada. Baixe e armazene os arquivos você mesmo antes disso — não há como atualizar um link expirado.

    • Name
      glb
      Type
      string
      Description

      URL para download do model.glb texturizado final.

    • Name
      obj_zip
      Type
      string
      Description

      URL para download de um pacote zip contendo model.obj, model.mtl e os PNGs de textura que seu MTL realmente referencia. Uma base de cor sólida envia apenas keycap-head.png; uma base padronizada também envia keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    URLs para download de imagens de processo intermediárias, indexadas por tipo. Mesmo ciclo de vida de URL que model_urls: assinadas, sem cabeçalho Authorization, válidas até expires_at, e estáveis quando a tarefa é relida. Tipos atualmente emitidos:

    • head_design — a imagem de design do candidato escolhido que a construção consumiu (sempre presente).
    • composite — a renderização de exibição do keycap finalizado do candidato escolhido (presente quando disponível).
    • base_canvas — a tela da base do keycap pintada (presente quando disponível).

    Trate o conjunto de chaves como aberto; novos tipos podem ser adicionados sem uma alteração de ruptura.

Exemplo de Objeto de Tarefa de Construção 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=***"
  }
}

Exemplo Completo

O fluxo completo: criar um protótipo a partir de uma foto, verificar seu status até SUCCEEDED, escolher um candidato de candidate_ids, criar uma construção com esse candidato, verificar a construção até SUCCEEDED, e então baixar o GLB e o pacote OBJ de model_urls.

O exemplo escolhe o primeiro candidato programaticamente. Em uma integração real, você exibiria a entrada image_urls para o usuário final e deixaria que ele escolhesse; o índice escolhido mapeia 1:1 para candidate_ids.

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