Creative Lab — Keycap API

Zamień zdjęcie źródłowe w pełnokolorową, niestandardową nakładkę (keycap) mechanicznej klawiatury w dwóch etapach: prototype generuje render projektu „gotowego keycapa” na podstawie zdjęcia wejściowego. Po zatwierdzeniu tego renderu build przekształca go w teksturowany model 3D keycapa w ramach jednego uruchomienia — generowanie modelu bazowego (white-model), automatyczne osadzenie i przycięcie na skalibrowanej domyślnej pozie, pełne kolorowanie modelu oraz finalny montaż odbywają się wewnątrz jednego zadania budowy. Oba etapy są połączone za pomocą input_task_id oraz candidate_id.

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

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

Utwórz zadanie prototypu keycapa

Wygeneruj render projektu gotowego keycapa na podstawie zdjęcia źródłowego. Wynik zadania zawiera tablicę image_urls (render wyświetlany gotowego keycapa) oraz równoległą tablicę candidate_ids; obie zawierają pojedynczy wpis. Wywołaj ten punkt końcowy ponownie, aby uzyskać kolejny render, jeśli wynik nie jest tym, czego oczekujesz — każde wywołanie jest rozliczane osobno. Przekaż candidate_id razem z identyfikatorem zadania prototypu do punktu końcowego budowania. Zapoznaj się z Obiektem zadania prototypu keycapa, aby poznać kształt odpowiedzi.

Parametry

  • Name
    image_url
    Type
    string
    Wymagane
    Description

    Zdjęcie źródłowe, które Meshy przekształci w obrazy projektu keycapa. Obecnie obsługujemy formaty .jpg, .jpeg, .png i .webp.

    Format jest wykrywany poprzez dekodowanie danych obrazu, a nie na podstawie rozszerzenia pliku w adresie URL — adres URL bez rozszerzenia lub taki, który przekierowuje, zadziała, o ile bajty da się zdekodować do obsługiwanego formatu. Przekierowania HTTP są śledzone. Orientacja EXIF jest normalizowana, więc obrócone zdjęcie z telefonu jest używane w takiej postaci, w jakiej wygląda.

    Ograniczenia: co najmniej 32 piksele po każdej stronie, co najwyżej 178 956 970 pikseli łącznie oraz co najwyżej 20 000 000 bajtów po pobraniu. W przypadku Data URI limit dotyczy bajtów po zdekodowaniu, więc sam plik źródłowy może mieć taki rozmiar — to tekst base64 jest o około jedną trzecią większy, co ma znaczenie dla treści żądania, ale nie dla tego limitu. Data URI musi deklarować typ zawartości image/* oraz ;base64.

    Istnieją dwa sposoby dostarczenia obrazu:

    • Publicznie dostępny adres URL: Adres URL dostępny z publicznego internetu.
    • Data URI: Zakodowany w base64 Data URI obrazu. Przykład Data URI: data:image/jpeg;base64,<your base64-encoded image data>.
  • Name
    name
    Type
    string
    Description

    Opcjonalna nazwa zadania do celów wyświetlania. Maksymalnie 100 znaków.

  • Name
    remove_background
    Type
    boolean
    domyślne false
    Description

    Gdy ustawione na true, render wyświetlany zwrócony w image_urls jest przezroczystym plikiem PNG w formacie RGBA z usuniętym tłem, dzięki czemu możesz nałożyć go na dowolne tło.

    Dotyczy to wyłącznie renderu wyświetlanego. Kandydat wykorzystywany przez punkt końcowy budowania nie jest tym objęty, więc wynik 3D jest identyczny w obu przypadkach.

Zwracane wartości

Właściwość result odpowiedzi zawiera id zadania nowo utworzonego zadania prototypu keycapa. Odpytuj punkt końcowy Pobierz zadanie lub subskrybuj strumień, aż zadanie osiągnie status SUCCEEDED, a następnie pobierz wpis z candidate_ids i przekaż go razem z identyfikatorem zadania do punktu końcowego budowania.

Tryby awarii

  • Name
    400 - Bad Request
    Description

    Żądanie było niepoprawne. Typowe przyczyny:

    • Brakujący parametr: image_url jest wymagany.
    • Nieprawidłowy format obrazu: Podany image_url nie ma obsługiwanego formatu (.jpg, .jpeg, .png, .webp).
    • Wymiary obrazu poza zakresem: Obraz jest zbyt mały, przekracza maksymalny rozmiar pliku lub przekracza maksymalną liczbę pikseli.
    • Nieosiągalny adres URL: Nie udało się pobrać image_url (404 lub timeout).
    • Nieprawidłowy Data URI: Ciąg base64 jest nieprawidłowo sformatowany.
    • Oznaczona treść: Obraz wejściowy został oznaczony przez moderation NSFW.
  • Name
    401 - Unauthorized
    Description

    Uwierzytelnianie nie powiodło się. Sprawdź swój klucz API.

  • Name
    402 - Payment Required
    Description

    Konto korzysta z planu darmowego (do tworzenia zadań wymagany jest płatny plan) lub ma niewystarczającą liczbę kredytów.

  • Name
    403 - Forbidden
    Description

    Obraz wejściowy został oznaczony przez moderation własności intelektualnej.

  • Name
    429 - Too Many Requests
    Description

    Przekroczono limit szybkości.

  • Name
    500 - Internal Server Error
    Description

    Wystąpił nieoczekiwany błąd po stronie serwera — na przykład usługa moderacji treści była niedostępna, przygotowanie obrazu wejściowego nie powiodło się, albo nie udało się utworzyć zadania. W takim przypadku żadne zadanie nie zostaje utworzone, więc ponowienie próby jest bezpieczne.

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

Utwórz zadanie budowy klawisza Keycap

Wygeneruj finalny, teksturowany model 3D klawisza (keycap) na podstawie zakończonego powodzeniem zadania prototypu oraz jednego z jego kandydatów. Pojedyncze zadanie budowy uruchamia cały potok od początku do końca — generowanie modelu białego na podstawie wybranego projektu, automatyczne osadzenie i przycięcie na podstawie klawisza przy użyciu skalibrowanej domyślnej pozy (bez potrzeby interaktywnej regulacji), kolorowanie całego modelu oraz finalny montaż i eksport. Budowa trwa zazwyczaj 3–7 minut, bliżej górnej granicy, gdy kilka procesów budowy uruchamianych jest jednocześnie. Zapoznaj się z Obiektem zadania budowy Keycap, aby poznać strukturę odpowiedzi.

Parametry

  • Name
    input_task_id
    Type
    string
    Wymagane
    Description

    Identyfikator zadania prototypu utworzonego za pośrednictwem tego samego punktu końcowego OpenAPI. Prototyp musi zostać utworzony przez to samo konto Meshy, musi osiągnąć status SUCCEEDED i musi wygenerować co najmniej jednego kandydata.

    Zadania prototypów utworzone za pośrednictwem aplikacji webowej nie są akceptowane — punkt końcowy budowy akceptuje wyłącznie zadania prototypów wygenerowane przez POST /openapi/creative-lab/keycap/v1/prototype i odrzuca każde inne źródło z kodem 404.

  • Name
    candidate_id
    Type
    string
    Wymagane
    Description

    Kandydat do zbudowania, pobrany z tablicy candidate_ids zakończonego powodzeniem zadania prototypu. Musi należeć do tego zadania; każda inna wartość zostanie odrzucona z kodem 400.

  • Name
    name
    Type
    string
    Description

    Opcjonalna nazwa zadania do celów wyświetlania. Maksymalnie 100 znaków.

options

Opcjonalne dostrojenie geometrii. Każde pole ma skalibrowaną wartość domyślną — wysyłaj tylko te, które chcesz nadpisać.

  • Name
    base_model
    Type
    string
    domyślne cherry-mx-1x1-r1
    Description

    Podstawa klawisza, na której ma zostać zbudowany model. Obecnie jedyną dostępną wartością jest cherry-mx-1x1-r1 — standardowy klawisz o profilu Cherry MX 1u. Planowane jest 3–5 dodatkowych powszechnie stosowanych rozmiarów standardowych; niestandardowe rozmiary nie są obsługiwane.

  • Name
    head_size_mm
    Type
    number
    domyślne 23
    Description

    Docelowy rozmiar rzeźbionej główki, w milimetrach: jej najdłuższy wymiar zostaje przeskalowany do tej wartości. Zakres: [10, 40]. Wartości powyżej około 32.9 mogą zostać zmniejszone, aby główka nadal mieściła się w limicie powierzchni ochronnej podstawy, więc dostarczony najdłuższy wymiar może być mniejszy niż żądany. Zastosowana wartość nie jest obecnie zwracana w obiekcie zadania — jeśli chcesz potwierdzić faktycznie otrzymany rozmiar, zmierz prostopadłościan ograniczający siatki keycap-head w pobranym modelu.

  • Name
    vertical_offset_mm
    Type
    number
    domyślne 0
    Description

    Przesunięcie pionowe stosowane do główki przed jej osadzeniem na podstawie, w milimetrach. Zakres: [-5, 5].

Zwracane wartości

Właściwość result odpowiedzi zawiera id zadania nowo utworzonego zadania budowy klawisza. Odpytuj punkt końcowy Pobierz zadanie lub subskrybuj strumień, dopóki zadanie nie osiągnie statusu SUCCEEDED, a następnie pobierz artefakty z model_urls.glb i model_urls.obj_zip.

Tryby awarii

  • Name
    400 - Bad Request
    Description

    Żądanie było niepoprawne. Typowe przyczyny:

    • Brakujący parametr: input_task_id i candidate_id są wymagane.
    • Nieprawidłowy UUID: input_task_id nie jest prawidłowym identyfikatorem UUID.
    • Zadanie nadrzędne nie zakończyło się powodzeniem: Zadanie prototypu, do którego się odwołano, nie osiągnęło jeszcze statusu SUCCEEDED.
    • Brak kandydatów: Zadanie prototypu zakończyło się powodzeniem, ale nie wygenerowało żadnych kandydatów.
    • Nieznany kandydat: candidate_id nie jest jednym z kandydatów zadania wejściowego.
    • Opcje poza zakresem: Jedno z pól options znalazło się poza dozwolonym zakresem lub zbiorem wartości enum.
  • Name
    401 - Unauthorized
    Description

    Uwierzytelnianie nie powiodło się. Sprawdź swój klucz API.

  • Name
    402 - Payment Required
    Description

    Konto korzysta z darmowego planu (do tworzenia zadań wymagany jest płatny plan) lub ma niewystarczającą liczbę kredytów.

  • Name
    404 - Not Found
    Description

    Zadanie prototypu, do którego się odwołano, nie istnieje, należy do innego użytkownika lub zostało utworzone za pośrednictwem aplikacji webowej (tylko zadania prototypów w trybie API mogą być łączone w łańcuch z zadaniem budowy).

  • Name
    429 - Too Many Requests
    Description

    Przekroczono limit szybkości.

  • Name
    500 - Internal Server Error
    Description

    Wystąpił nieoczekiwany błąd po stronie serwera — na przykład usługa moderacji treści była niedostępna, nie udało się przygotować obrazu wejściowego lub nie można było utworzyć zadania. W takim przypadku żadne zadanie nie zostaje utworzone, więc ponowienie próby jest bezpieczne.

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

Pobieranie zadania Keycap

Pobiera zadanie prototypu lub builda na podstawie prawidłowego id zadania. Ścieżka URL musi odpowiadać etapowi zadania — zadanie builda pobrane przez /prototype/:id zwróci 404, i odwrotnie.

Zapoznaj się z sekcją The Keycap Prototype Task Object oraz The Keycap Build Task Object, aby poznać kształty odpowiedzi.

Parametry

  • Name
    id
    Type
    path
    Description

    Unikalny identyfikator zadania keycap do pobrania.

Zwraca

Odpowiedź zawiera obiekt zadania keycap. Jego kształt zależy od tego, który etap został zażądany.

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

Usuwanie zadania Keycap

Anuluje zadanie keycap. Jeśli zadanie nadal ma status PENDING, kredyty zużyte w momencie utworzenia zostają zwrócone. Zadania, które są już w stanie IN_PROGRESS, są anulowane bez zwrotu kredytów (worker może już zużywać zasoby). Zadań, które osiągnęły już stan końcowy (SUCCEEDED, FAILED, CANCELED), nie można anulować.

Ścieżka URL musi odpowiadać etapowi zadania — wywołanie DELETE na /prototype/:buildId zwróci 404.

Parametry ścieżki

  • Name
    id
    Type
    path
    Description

    Unikalny identyfikator zadania keycap do anulowania.

Zwraca

Zwraca 204 No Content w przypadku powodzenia, z pustym ciałem odpowiedzi.

Tryby błędów

  • Name
    400 - Bad Request
    Description

    Zadanie jest już w stanie końcowym i nie można go anulować.

  • Name
    404 - Not Found
    Description

    Zadanie nie istnieje, należy do innego użytkownika lub jego etap nie odpowiada ścieżce URL.

  • Name
    500 - Internal Server Error
    Description

    Podczas anulowania wystąpił nieoczekiwany błąd po stronie serwera. Zadanie mogło zostać anulowane lub nie — odczytaj je ponownie, aby to potwierdzić przed ponowną próbą.

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

Streamowanie zadania Keycap

Umożliwia strumieniowanie aktualizacji zadania keycap w czasie rzeczywistym za pomocą Server-Sent Events (SSE). Ścieżka URL musi odpowiadać etapowi zadania — otwarcie strumienia pod adresem /prototype/:buildId/stream emituje pojedynczy ładunek event: error ze status_code: 404 i zamyka strumień.

Parametry

  • Name
    id
    Type
    path
    Description

    Unikalny identyfikator zadania keycap do strumieniowania.

Zwraca

Zwraca strumień obiektów zadania Keycap Prototype lub Keycap Build w formie Server-Sent Events. Każda ramka zawiera pełny obiekt zadania dla danego etapu — w tej samej postaci, jaką zwraca punkt końcowy Get — więc gdy zadanie ma status PENDING lub IN_PROGRESS, pola wyjściowe po prostu nie są jeszcze wypełnione (null, [] lub {}), a finished_at ma wartość null.

Request

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

Response Stream

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

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

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

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

List Keycap Tasks

Pobierz stronicowaną listę zadań keycap dla pojedynczego etapu. Ścieżka URL określa etap — /prototype zwraca zadania prototypowe, a /build zwraca zadania budowania. Zadania z drugiego etapu nie są uwzględniane w żadnej z odpowiedzi.

Parametry ścieżki

  • Name
    stage
    Type
    path
    Wymagane
    Description

    prototype albo build. Kolekcja zwraca tylko zadania, których etap odpowiada URL-owi — pobranie /prototype nigdy nie zwróci zadań budowania i odwrotnie.

Parametry zapytania

  • Name
    page_num
    Type
    integer
    domyślne 1
    Description

    Numer strony do stronicowania.

  • Name
    page_size
    Type
    integer
    domyślne 10
    Description

    Limit rozmiaru strony. Maksymalna dozwolona wartość to 100 elementów.

  • Name
    sort_by
    Type
    string
    domyślne -created_at
    Description

    Pole, według którego dane są sortowane. Dostępne wartości:

    • +created_at: Sortuj według czasu utworzenia rosnąco.
    • -created_at: Sortuj według czasu utworzenia malejąco.

Zwraca

Zwraca stronicowaną listę obiektów zadań danego etapu — albo obiekt zadania prototypu keycap przy pobieraniu listy /prototype, albo obiekt zadania budowania keycap przy pobieraniu listy /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"
    ]
  }
]

Obiekt zadania prototypu nakładki klawisza (Keycap Prototype Task)

Obiekt Keycap Prototype Task jest jednostką pracy, którą Meshy śledzi, aby wygenerować jeden obraz gotowego projektu nakładki klawisza na podstawie źródłowego zdjęcia. Wynik tego etapu jest łączony z etapem budowy za pomocą input_task_id oraz candidate_id.

Właściwości

  • Name
    id
    Type
    string
    Description

    Unikalny identyfikator zadania. Chociaż jako szczegół implementacyjny używamy identyfikatorów zadań w postaci k-sortowalnych UUID, nie należy przyjmować żadnych założeń dotyczących formatu tego id.

  • Name
    type
    Type
    string
    Description

    Typ zadania. Wartość to creative-lab-keycap-prototype.

  • Name
    name
    Type
    string
    Description

    Nazwa zadania podana podczas jego tworzenia. Pusty ciąg znaków, jeśli nazwa nie została podana.

  • Name
    status
    Type
    string
    Description

    Status zadania. Możliwe wartości to jedna z: PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Postęp zadania (progress). Jeśli zadanie nie zostało jeszcze rozpoczęte, ta właściwość wynosi 0. Gdy zadanie zakończy się powodzeniem, wartość ta zmieni się na 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Znacznik czasu utworzenia zadania, w milisekundach.

  • Name
    started_at
    Type
    timestamp
    Description

    Znacznik czasu rozpoczęcia zadania, w milisekundach. Jeśli zadanie nie zostało jeszcze rozpoczęte, ta właściwość wynosi 0.

  • Name
    finished_at
    Type
    timestamp
    Description

    Znacznik czasu zakończenia zadania, w milisekundach. Jeśli zadanie nie zostało jeszcze zakończone, ta właściwość wynosi 0.

  • Name
    expires_at
    Type
    timestamp
    Description

    Znacznik czasu wygaśnięcia wyniku zadania, w milisekundach.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Liczba poprzedzających zadań.

  • Name
    task_error
    Type
    object
    Description

    Szczegóły błędu dla nieudanych zadań. Zobacz Błędy, aby poznać pełną strukturę obiektu task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Liczba kredytów zużytych przez to zadanie. Zadanie, które osiąga status SUCCEEDED, jest obciążane pełną kwotą za swój etap. Zadanie, które nigdy nie zostało utworzone (błąd 4xx w momencie żądania, w tym odrzucenie przez moderation), w ogóle nie generuje obciążenia. Zadanie, które osiąga status FAILED, zwraca 0 — opłata jest zwracana, w tym w przypadku asynchronicznej blokady moderation. Anulowanie za pomocą DELETE powoduje zwrot środków tylko wtedy, gdy zadanie nadal ma status PENDING; zadanie, które jest już IN_PROGRESS, pozostaje obciążone, ponieważ praca została już wykonana.

  • Name
    image_urls
    Type
    array of strings
    Description

    Pobieralny URL renderu gotowego projektu nakładki klawisza — czyli tego, jak dany kandydat wygląda jako gotowa nakładka klawisza. Zawiera jeden wpis; image_urls[i] odpowiada candidate_ids[i]. Puste, dopóki zadanie nie osiągnie statusu SUCCEEDED. URL służy wyłącznie do wyświetlania; punkt końcowy budowy przyjmuje candidate_ids, a nie te adresy URL. Ten sam cykl życia URL co w przypadku model_urls: podpisany, bez nagłówka Authorization, ważny do momentu expires_at i stabilny przy ponownym odczycie zadania.

  • Name
    candidate_ids
    Type
    array of strings
    Description

    Nieprzezroczyste identyfikatory kandydatów, równoległe do image_urls. Przekaż wpis odpowiadający wybranemu przez Ciebie projektowi jako candidate_id żądania budowy. Nie należy przyjmować żadnych założeń dotyczących formatu tych identyfikatorów.

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

Obiekt zadania budowy Keycap

Obiekt zadania budowy Keycap (Keycap Build Task) to jednostka pracy śledzona przez Meshy w celu wygenerowania finalnego, teksturowanego modelu 3D klawisza (keycap) na podstawie zakończonego powodzeniem zadania prototypu oraz wybranego kandydata. Pojedyncza budowa uruchamia pełny potok — generowanie modelu bazowego (white-model), automatyczne osadzanie i wycinanie, kolorowanie, montaż oraz eksport.

Właściwości

  • Name
    id
    Type
    string
    Description

    Unikalny identyfikator zadania.

  • Name
    type
    Type
    string
    Description

    Typ zadania. Wartość to creative-lab-keycap-build.

  • Name
    name
    Type
    string
    Description

    Nazwa zadania podana podczas jego tworzenia. Pusty ciąg znaków, jeśli nie podano nazwy.

  • Name
    status
    Type
    string
    Description

    Status zadania. Możliwe wartości to jedna z: PENDING, IN_PROGRESS, SUCCEEDED, FAILED, CANCELED.

  • Name
    progress
    Type
    integer
    Description

    Postęp zadania. Jeśli zadanie jeszcze się nie rozpoczęło, ta wartość wynosi 0. Gdy zadanie zakończy się powodzeniem, wartość ta zmieni się na 100.

  • Name
    created_at
    Type
    timestamp
    Description

    Znacznik czasu utworzenia zadania, w milisekundach.

  • Name
    started_at
    Type
    timestamp
    Description

    Znacznik czasu rozpoczęcia zadania, w milisekundach.

  • Name
    finished_at
    Type
    timestamp
    Description

    Znacznik czasu zakończenia zadania, w milisekundach.

  • Name
    expires_at
    Type
    timestamp
    Description

    Znacznik czasu wygaśnięcia wyniku zadania, w milisekundach.

  • Name
    preceding_tasks
    Type
    integer
    Description

    Liczba poprzedzających zadań. Ma znaczenie tylko wtedy, gdy status to PENDING.

  • Name
    task_error
    Type
    object
    Description

    Szczegóły błędu dla nieudanych zadań. Zobacz Błędy, aby poznać pełny opis obiektu task_error.

  • Name
    consumed_credits
    Type
    integer
    Description

    Liczba kredytów zużytych przez to zadanie. Zadanie, które osiągnie status SUCCEEDED, jest obciążane pełną kwotą za swój etap. Zadanie, które nigdy nie zostało utworzone (błąd 4xx w momencie żądania, w tym odrzucenie przez moderation) nie jest obciążane w ogóle. Zadanie, które osiągnie status FAILED, zwraca 0 — opłata jest zwracana, w tym w przypadku asynchronicznej blokady moderation. Anulowanie za pomocą DELETE zwraca opłatę tylko wtedy, gdy zadanie ma jeszcze status PENDING; zadanie już będące IN_PROGRESS pozostaje obciążone, ponieważ praca została już wykonana.

  • Name
    model_urls
    Type
    object
    Description

    Adresy URL umożliwiające pobranie wygenerowanych plików modelu. Zarówno paczka GLB, jak i OBJ są eksportowane w rzeczywistej skali milimetrowej, w układzie Y-up, z przodem klawisza skierowanym w stronę +Z. Siatki nazwane są keycap-head i keycap-base; gdy podstawa korzysta z zapasowego wypełnienia wzorem, obecna jest również trzecia siatka keycap-base-interior dla wnęki trzpienia. Nie zakładaj, że zawsze będą dokładnie dwie siatki.

    Są to podpisane adresy URL: pobieraj je bez nagłówka Authorization. Pozostają ważne do momentu expires_at, czyli 3 dni po finished_at, a ponowny odczyt zadania w tym okresie zwraca dokładnie ten sam adres URL, a nie nowo podpisany. Pobierz i zapisz pliki samodzielnie przed tym terminem — nie ma możliwości odświeżenia wygasłego linku.

    • Name
      glb
      Type
      string
      Description

      Adres URL umożliwiający pobranie finalnego, teksturowanego pliku model.glb.

    • Name
      obj_zip
      Type
      string
      Description

      Adres URL umożliwiający pobranie paczki zip zawierającej model.obj, model.mtl oraz pliki PNG tekstur, do których faktycznie odwołuje się plik MTL. Podstawa w jednolitym kolorze zawiera tylko keycap-head.png; podstawa ze wzorem zawiera dodatkowo keycap-base.png.

  • Name
    process_image_urls
    Type
    object
    Description

    Adresy URL umożliwiające pobranie pośrednich obrazów procesu, indeksowane według rodzaju. Ten sam cykl życia adresu URL co w model_urls: podpisany, bez nagłówka Authorization, ważny do expires_at, i stabilny przy ponownym odczycie zadania. Obecnie generowane rodzaje:

    • head_design — obraz projektu wybranego kandydata, wykorzystany przez budowę (zawsze obecny).
    • composite — render prezentacyjny gotowego klawisza dla wybranego kandydata (obecny, gdy dostępny).
    • base_canvas — pomalowane płótno podstawy klawisza (obecne, gdy dostępne).

    Traktuj zbiór kluczy jako otwarty; nowe rodzaje mogą zostać dodane bez wprowadzania zmiany łamiącej kompatybilność.

Example Keycap Build Task Object

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

Kompletny przykład

Kompletny przepływ: utworzenie prototypu ze zdjęcia, odpytywanie go aż do SUCCEEDED, wybranie kandydata z candidate_ids, utworzenie kompilacji z tym kandydatem, odpytywanie kompilacji aż do SUCCEEDED, a następnie pobranie pliku GLB oraz paczki OBJ z model_urls.

Przykład wybiera pierwszego kandydata programowo. W rzeczywistej integracji należałoby wyświetlić użytkownikowi końcowemu wpisy z image_urls i pozwolić mu dokonać wyboru; wybrany indeks mapuje się 1:1 na candidate_ids.

Complete flow

POST
/openapi/creative-lab/keycap/v1
#!/usr/bin/env bash
set -euo pipefail

# Requires curl and jq. Point IMAGE_PATH at a local photo, or IMAGE_URL at a public one:
#   export MESHY_API_KEY=msy_...
#   export IMAGE_PATH=./portrait.jpg          # or: export IMAGE_URL=https://...
: "${MESHY_API_KEY:?export MESHY_API_KEY first}"
if [[ -z "${IMAGE_PATH:-}" && -z "${IMAGE_URL:-}" ]]; then
  echo "export IMAGE_PATH (local file) or IMAGE_URL (public url) first" >&2
  exit 1
fi

BASE="https://api.meshy.ai/openapi/creative-lab/keycap/v1"
AUTH="Authorization: Bearer $MESHY_API_KEY"

# api METHOD URL [curl args...] -> prints the response body, non-zero on failure.
# Note we do not use -f/--fail: it discards the body, and the body is the only
# place the reason appears.
api() {
  local method=$1 url=$2 out http_code body
  shift 2
  out=$(curl --silent --show-error --max-time 60 --write-out $'\n%{http_code}' \
    -X "$method" "$url" -H "$AUTH" "$@") || return 1
  http_code=${out##*$'\n'}
  body=${out%$'\n'*}
  if ((http_code >= 400)); then
    echo "HTTP $http_code for $url: $body" >&2
    return 1
  fi
  printf '%s' "$body"
}

# Each task gets its own 40-minute budget.
poll() {
  local kind=$1 id=$2 delay=5 task_status deadline
  deadline=$(($(date +%s) + 2400))
  while :; do
    if (($(date +%s) >= deadline)); then
      echo "gave up waiting for $kind $id" >&2
      return 1
    fi
    task_status=$(api GET "$BASE/$kind/$id" | jq -r '.status')
    echo "$kind: $task_status"
    case "$task_status" in
    SUCCEEDED) return 0 ;;
    FAILED | CANCELED) return 1 ;;
    esac
    sleep "$delay"
    delay=$((delay * 2 > 30 ? 30 : delay * 2))
  done
}

# Build the request body in a file. A base64 data URI must never go on the
# command line or into an exported variable - a photo of any real size will
# exceed the OS argument limit.
BODY=$(mktemp)
trap 'rm -f "$BODY"' EXIT
if [[ -n "${IMAGE_PATH:-}" ]]; then
  # Declare the real type: the API accepts JPEG, PNG and WebP.
  case "$(printf '%s' "${IMAGE_PATH##*.}" | tr 'A-Z' 'a-z')" in
    png) MIME=image/png ;;
    webp) MIME=image/webp ;;
    *) MIME=image/jpeg ;;
  esac
  {
    printf '{"image_url":"data:%s;base64,' "$MIME"
    base64 <"$IMAGE_PATH" | tr -d '\n'
    printf '"}'
  } >"$BODY"
else
  printf '{"image_url":"%s"}' "$IMAGE_URL" >"$BODY"
fi

# 1. Create the prototype task
PROTO_ID=$(api POST "$BASE/prototype" \
  -H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')

# 2. Wait for the design render
poll prototype "$PROTO_ID"

# 3. Pick a candidate (first one here; show image_urls to a user in production)
CANDIDATE_ID=$(api GET "$BASE/prototype/$PROTO_ID" | jq -r '.candidate_ids[0]')

# 4. Create the build task
jq -n --arg p "$PROTO_ID" --arg c "$CANDIDATE_ID" \
  '{input_task_id: $p, candidate_id: $c}' >"$BODY"
BUILD_ID=$(api POST "$BASE/build" \
  -H 'Content-Type: application/json' --data-binary @"$BODY" | jq -r '.result')

# 5. Wait for the model (a build usually takes 3-7 minutes)
poll build "$BUILD_ID"

# 6. Download the artifacts. These are signed URLs: no Authorization header,
#    and they stay valid for 3 days after the task finishes.
TASK=$(api GET "$BASE/build/$BUILD_ID")
curl --silent --show-error --fail --max-time 900 \
  -o keycap.glb "$(jq -r '.model_urls.glb' <<<"$TASK")"
curl --silent --show-error --fail --max-time 900 \
  -o keycap-obj.zip "$(jq -r '.model_urls.obj_zip' <<<"$TASK")"
echo "Done: keycap.glb + keycap-obj.zip"