Creative Lab — Keycap API

Transforme uma foto de origem numa tecla de teclado mecânico personalizada a cores em duas etapas: protótipo gera uma renderização de design de "tecla finalizada" a partir da sua foto de entrada. Uma vez confirmado esse render, construir transforma-o num modelo 3D de tecla texturizado numa única execução — geração de modelo branco, posicionamento e corte automáticos numa pose padrão calibrada, coloração do modelo completo e montagem final, tudo acontece dentro de uma única tarefa de construção. As duas etapas estão ligadas 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 uma renderização de design de keycap finalizada a partir da foto de origem. O resultado da tarefa contém um array image_urls (a renderização de exibição do keycap finalizado) e um array paralelo candidate_ids; ambos contêm uma única entrada. Chame este endpoint novamente para outra renderização se o resultado não for o que deseja — cada chamada é cobrada separadamente. Passe o candidate_id juntamente 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 é detetado ao decodificar os dados da imagem, não a partir da extensão do ficheiro no URL — um URL sem extensão, ou um que redireciona, funciona desde que os bytes sejam decodificados para um formato suportado. Redirecionamentos HTTP são seguidos. A orientação EXIF é normalizada, portanto, uma foto de telemóvel rodada é usada da forma como aparece.

    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 descarregados. Para um Data URI, o limite aplica-se aos bytes decodificados, portanto, o ficheiro de origem pode ter até esse tamanho — é o texto base64 que é cerca de um terço maior, o que importa para o corpo do seu pedido, 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: Um URL acessível a partir da internet pública.
    • Data URI: Um Data URI codificado em base64 da imagem. Exemplo de um Data URI: data:image/jpeg;base64,<your base64-encoded image data>.
  • Name
    name
    Type
    string
    Description

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

  • Name
    remove_background
    Type
    boolean
    predefinição false
    Description

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

    Isto aplica-se apenas à renderização de exibição. O candidato que o endpoint de construção consome não é afetado, portanto, o resultado 3D é idêntico de qualquer maneira.

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 subscreva o stream até que a tarefa atinja SUCCEEDED, depois pegue a entrada de candidate_ids e passe-a, juntamente com o ID da tarefa, para o endpoint de construção.

Modos de Falha

  • Name
    400 - Bad Request
    Description

    O pedido foi inaceitável. Causas comuns:

    • Parâmetro em falta: 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 ficheiro ou excede o número máximo de pixels.
    • URL inacessível: O image_url não pôde ser descarregado (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 a sua chave de API.

  • Name
    402 - Payment Required
    Description

    A conta está no plano gratuito (é necessário um plano pago para criar tarefas) ou não tem 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

    Excedeu o seu limite de taxa.

  • Name
    500 - Internal Server Error
    Description

    Ocorreu um erro inesperado do 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, portanto, tentar novamente é seguro.

Pedido

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

Resposta

{
  "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 um keycap a partir de uma tarefa de protótipo bem-sucedida e um dos 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 normalmente demora 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 a forma 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 da aplicação web não são aceites — 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 construir, 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 deseja substituir.

  • Name
    base_model
    Type
    string
    predefiniçã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 planeados 3–5 tamanhos padrão adicionais; tamanhos personalizados não são suportados.

  • Name
    head_size_mm
    Type
    number
    predefinição 23
    Description

    Tamanho alvo da cabeça esculpida, em milímetros: a sua dimensão mais longa é 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, portanto, a dimensão mais longa entregue pode ser menor do que a solicitada. O valor aplicado não é refletido de volta no objeto da tarefa hoje — se 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
    predefiniçã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 da nova tarefa de construção de keycap criada. Consulte o endpoint Obter uma Tarefa ou subscreva o stream até que a tarefa atinja SUCCEEDED, depois baixe os artefatos de model_urls.glb e model_urls.obj_zip.

Modos de Falha

  • Name
    400 - Bad Request
    Description

    O pedido foi inaceitável. Causas comuns:

    • Parâmetro em falta: 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 atingiu 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 a sua chave de API.

  • Name
    402 - Payment Required
    Description

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

  • Name
    404 - Not Found
    Description

    A tarefa de protótipo referenciada não existe, pertence a um utilizador diferente, ou foi criada através da aplicação web (apenas tarefas de protótipo em modo API encadeiam em construção).

  • Name
    429 - Too Many Requests
    Description

    Excedeu o 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, portanto, 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 dado um id de tarefa válido. O caminho do URL deve corresponder à fase da tarefa — uma tarefa de construção obtida 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 recuperar.

Retornos

A resposta contém o objeto da tarefa de keycap. O formato depende de qual fase foi solicitada.

Pedido

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

Resposta de Protótipo

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

Resposta de Construção

{
  "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 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 a consumir recursos). Tarefas que já atingiram um estado terminal (SUCCEEDED, FAILED, CANCELED) não podem ser canceladas.

O caminho do URL deve corresponder à fase da tarefa — DELETE em /prototype/:buildId retorna 404.

Parâmetros do Caminho

  • Name
    id
    Type
    path
    Description

    Identificador único para a tarefa de keycap a cancelar.

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á num estado terminal e não pode ser cancelada.

  • Name
    404 - Not Found
    Description

    A tarefa não existe, pertence a um utilizador diferente, ou a sua fase não corresponde ao caminho do URL.

  • Name
    500 - Internal Server Error
    Description

    Ocorreu um erro inesperado do lado do servidor ao cancelar. A tarefa pode ou não ter sido cancelada — releia-a 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 do URL deve corresponder à fase 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 transmitir.

Retornos

Retorna uma transmissão de objetos de tarefa Keycap Prototype ou Keycap Build 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 das 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 estã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 corresponde à URL — buscar /prototype nunca retorna tarefas de construção e vice-versa.

Parâmetros de Consulta

  • Name
    page_num
    Type
    integer
    predefinição 1
    Description

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

  • Name
    page_size
    Type
    integer
    predefinição 10
    Description

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

  • Name
    sort_by
    Type
    string
    predefinição -created_at
    Description

    Campo para ordenar. Valores disponíveis:

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

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 do Protótipo de Keycap

O objeto de Tarefa do 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. O resultado desta fase é encadeado na fase de construção através de 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, não deve fazer quaisquer 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, isto 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 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 da sua fase. Uma tarefa que nunca é criada (um 4xx no momento do pedido, incluindo uma rejeição de moderação) não é cobrada de todo. 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, porque o trabalho foi gasto.

  • Name
    image_urls
    Type
    array of strings
    Description

    URL descarregável 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. O URL é apenas para exibição; o endpoint de construção consome candidate_ids, não estes URLs. Mesmo ciclo de vida do URL que model_urls: assinado, sem cabeçalho Authorization, válido 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 do pedido de construção. Não faça quaisquer suposições sobre o formato destes ids.

Exemplo de Objeto de Tarefa do 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 a keycap 3D final texturizada a partir de uma tarefa de protótipo bem-sucedida e um candidato escolhido. Uma única construção executa todo o pipeline — geração de modelo branco, posicionamento 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

    Estado 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, isto 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 estado é 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 da sua fase. Uma tarefa que nunca é criada (um 4xx no momento da solicitação, incluindo uma rejeição de moderação) não é cobrada de todo. 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, porque o trabalho já foi gasto.

  • Name
    model_urls
    Type
    object
    Description

    URLs para download dos artefatos do modelo gerado. Tanto o pacote GLB quanto o OBJ são exportados em escala milimétrica do mundo real, Y-up, com a frente da keycap voltada para +Z. As malhas são nomeadas keycap-head e keycap-base; quando a base recorre a 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: obtenha-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 o URL idêntico em vez de um novo assinado. Faça o download 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 final texturizado.

    • 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 da keycap finalizada do candidato escolhido (presente quando disponível).
    • base_canvas — a tela da base da keycap pintada (presente quando disponível).

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

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 até SUCCEEDED, escolher um candidato de candidate_ids, criar uma construção com esse candidato, verificar a construção até SUCCEEDED, e depois descarregar o pacote GLB e OBJ de model_urls.

O exemplo escolhe o primeiro candidato programaticamente. Numa integração real mostraria a entrada image_urls ao utilizador 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"