GlossiDocs
Open Glossi
API

Variants and logos

List and create model variants, add them to a project, choose which variant each model wears, render only the ones you want, and set the logo in each decal slot, through the REST API or an MCP agent.

A variant is one look of a model: a colorway, a finish, a trim. The REST API and the MCP connector use the same services as the app, so a variant created through the API appears on the model page, and a logo set through the API prints on the production file.

Access

REST requests use your workspace API key in X-API-Key. Paths below are relative to https://api.glossi.io/api/v1. MCP tools take the same arguments by name, plus an optional workspaceId. Both require a plan with API access.

Variant and slot IDs are GUIDs and are accepted with or without braces or dashes. Errors use the standard shape, { "error": { "code": "...", "message": "..." } }: 400 VALIDATION_ERROR for bad input, 404 NOT_FOUND for a model, project, variant, slot, or decal that does not exist in your workspace. A material or tag that does not exist is a 400.

RESTMCP tool
GET /models/:modelId/variantslist_model_variants
POST /models/:modelId/variantscreate_model_variant
POST /models/:modelId/variants/:variantId/previewrequest_variant_preview
POST /projects/:projectId/variantsadd_variants_to_project
GET /projects/:projectId/variant-choicesget_project_variant_choices
PUT /projects/:projectId/variant-choices/:modelIdset_project_variant_choice
POST /renders with settings.variantsToRenderrender with variantIds
GET /models/:modelId/decal-slotsget_decal_slots
PUT /models/:modelId/variants/:variantId/decal-slots/:slotIdset_decal_assignment
PUT /models/:modelId/variants/:variantId/decal-slots/:slotId/logo-sizeset_decal_logo_size

List a model's variants

curl 'https://api.glossi.io/api/v1/models/MODEL_ID/variants?limit=50' \
  -H "X-API-Key: $GLOSSI_API_KEY"
QueryDefault
limit501 to 100.
afternextCursor from the previous page.
searchMatches the variant's name, tags, and property values. Up to 200 characters.
purposePREPARED_STYLE, STANDARD_COLORWAY or TEAM_DESIGN: only that kind of variant.
{
  "materialSlots": ["Body", "Trim"],
  "variants": [
    {
      "id": "8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f",
      "modelId": "MODEL_ID",
      "name": "Home Red",
      "source": "web",
      "purpose": null,
      "sourceVariantId": null,
      "sourceVariantName": null,
      "styleVariantId": null,
      "styleVariantName": null,
      "materialAssignments": [{ "groupName": "Body", "materialId": "MATERIAL_ID" }],
      "tags": [],
      "previewStatus": "READY",
      "createdAt": "2026-09-29T10:12:00.000Z",
      "updatedAt": "2026-09-29T10:12:00.000Z"
    }
  ],
  "total": 1,
  "hasMore": false,
  "nextCursor": null
}

materialSlots lists the model's material slots: the names a new variant can assign a material to. It is empty for a model processed before slots were recorded.

source is web for variants defined on the model page or through the API, and studio for variants made in the Studio, which are edited there. A studio variant's materialAssignments is empty; its materials live in the Studio.

purpose places a variant in a catalogue of styles, colorways and team designs, and is null for an ordinary variant. sourceVariantId and sourceVariantName name the variant it was copied from, and styleVariantId and styleVariantName the style it descends from. Both are fixed when the variant is created.

previewStatus is where the variant's 3D preview stands. See Variant previews.

Create a variant

A variant is a name plus which library material each of the model's material slots wears. groupName is one of the model's materialSlots. When the model has slots listed, a name that is not one of them is refused, and a name that differs only in letter case is saved in the listed spelling.

curl -X POST 'https://api.glossi.io/api/v1/models/MODEL_ID/variants' \
  -H "X-API-Key: $GLOSSI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "name": "Home Red",
    "materialAssignments": [
      { "groupName": "Body", "materialId": "MATERIAL_ID" },
      { "groupName": "Trim", "materialId": "OTHER_MATERIAL_ID" }
    ]
  }'
FieldRequired
nameyesUp to 80 characters.
materialAssignmentsunless copyingOne entry per slot to set, up to 200. Slots you leave out keep the model's own material.
copyFromVariantIdnoStart from what another variant of the same model wears, and its logos. materialAssignments override those slots.
purposenoPREPARED_STYLE, STANDARD_COLORWAY or TEAM_DESIGN. A team design is copied from a STANDARD_COLORWAY and wears its materials.
tagIdsnoWorkspace tag IDs, up to 50.

The response is the new variant, 201. A new variant starts with the base variant's logos in every decal slot, or the source variant's when you copy. Its 3D preview starts building straight away, so previewStatus is usually PENDING.

A copy keeps everything else about its source's look too, including finishes and colors adjusted in the Studio, and only the slots you list change. Until the copy is opened in the Studio, it picks up later Studio changes to its source. Changing a variant's materials later changes only the slots you change; slots adjusted in the Studio keep their adjustments.

Variant previews

A variant created or changed through the API or on the model page gets a 3D preview of its own, built on a render server from its materials and logos. Creating a variant, changing its materialAssignments, and setting, sizing or clearing one of its logos each start a new preview. Changes made within a few seconds of each other share one build. Studio variants get their preview when you leave the Studio.

previewStatus
PENDINGBeing built. Usually a few minutes; poll the variants list until it changes.
READYThe preview matches the variant.
FAILEDThe last build failed. Request it again.
NEEDS_PROJECTThe model is in no project yet, so it cannot be loaded. Open it in the Studio once, then request it again.
NONENo preview yet, for example a variant made before previews were automatic.

Request a preview

curl -X POST 'https://api.glossi.io/api/v1/models/MODEL_ID/variants/VARIANT_ID/preview' \
  -H "X-API-Key: $GLOSSI_API_KEY"

Builds the variant's preview again: to retry a FAILED one, or to make one for a variant from before previews were automatic. The response is 202 while it builds and 200 when it cannot start:

{ "modelId": "MODEL_ID", "variantId": "8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f", "previewStatus": "PENDING" }

previewStatus is PENDING, or NEEDS_PROJECT when the model is in no project. A Studio variant is a 400: its preview is made when you leave the Studio.

Add variants to a project

A project keeps a list of the variants it works with. A project with no list works with every variant of its model, so adding the first one narrows the project to the variants listed.

curl -X POST 'https://api.glossi.io/api/v1/projects/PROJECT_ID/variants' \
  -H "X-API-Key: $GLOSSI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "variantIds": ["8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f"] }'

Up to 50 per request. Each variant must belong to a model already in the project. Adding one that is already there changes nothing. The response lists every variant the project now has.

Choose the variant a model wears

A project can hold several models. Each one wears a variant, and the choice belongs to the project: the same model can wear a different variant in another project.

curl -X PUT 'https://api.glossi.io/api/v1/projects/PROJECT_ID/variant-choices/MODEL_ID' \
  -H "X-API-Key: $GLOSSI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "variantId": "8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f" }'

MODEL_ID must be a model in the project, and variantId one of that model's variants. Send null, or the model's baseVariantId, to clear the choice. Setting the same choice again changes nothing. If the project keeps a list of that model's variants, the chosen variant is added to it.

The response, and GET /projects/PROJECT_ID/variant-choices, list every model in the project in order:

{
  "projectId": "PROJECT_ID",
  "choices": [
    { "modelId": "FIRST_MODEL_ID", "variantId": null },
    { "modelId": "MODEL_ID", "variantId": "8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f" }
  ]
}

variantId is null for a model with no choice. Removing a model from the project, or deleting the variant, clears its choice.

Use this for what a model wears while the project renders. To render several variants of the project's first model in one request, use variantsToRender below.

Render only some variants

POST /renders renders every variant the project works with. Narrow it with settings.variantsToRender, up to 50:

curl -X POST 'https://api.glossi.io/api/v1/renders' \
  -H "X-API-Key: $GLOSSI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{
    "projectIds": ["PROJECT_ID"],
    "settings": { "variantsToRender": ["8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f"] }
  }'

Every ID must be a variant each listed project can render, otherwise the request fails with a 400 naming the IDs and nothing starts. Add the variant to the project first. Only variants of a project's first model can be rendered. The MCP render tool takes the same list as variantIds.


Decal slots

A decal slot is a place on the model that takes a logo: a chest, a sleeve, a back number. Slots are created in the Studio. Which logo sits in a slot is set per variant, from the decal library.

List slots and logos

curl 'https://api.glossi.io/api/v1/models/MODEL_ID/decal-slots' \
  -H "X-API-Key: $GLOSSI_API_KEY"
{
  "modelId": "MODEL_ID",
  "baseVariantId": "11111111-1111-4111-8111-111111111111",
  "slots": [{ "slotId": "22222222-2222-4222-8222-222222222222", "name": "Chest", "widthCm": 10, "heightCm": 8 }],
  "assignments": [
    {
      "variantId": "8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f",
      "slotId": "22222222-2222-4222-8222-222222222222",
      "decalId": "DECAL_ID",
      "imageKey": "workspaces/.../DECALS/DECAL_ID/source.png",
      "width": 800,
      "height": 600,
      "logoWidthCm": null,
      "logoHeightCm": null,
      "decorationMethod": "Screen print"
    }
  ]
}

baseVariantId is the model's original look. It is null for a model that has never been opened in the Studio.

curl -X PUT 'https://api.glossi.io/api/v1/models/MODEL_ID/variants/VARIANT_ID/decal-slots/SLOT_ID' \
  -H "X-API-Key: $GLOSSI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "decalId": "DECAL_ID" }'

decalId is a decal from your library whose upload is confirmed (READY). Send null to clear the slot. VARIANT_ID is a variant of the model or its baseVariantId. Replacing a logo keeps the slot's decoration method.

{
  "cleared": false,
  "assignment": {
    "variantId": "8f0c2d1e-5b7a-4c3e-9f21-0a6b3c4d5e6f",
    "slotId": "22222222-2222-4222-8222-222222222222",
    "decalId": "DECAL_ID",
    "imageKey": "workspaces/.../DECALS/DECAL_ID/source.png",
    "width": 800,
    "height": 600,
    "logoWidthCm": null,
    "logoHeightCm": null,
    "decorationMethod": null
  }
}

A changed logo makes that variant's production views out of date. The next production file export captures them again.

By default a logo is fitted to its slot. To print it at a set size on one variant, give the full artwork canvas in centimeters, transparent padding included:

curl -X PUT 'https://api.glossi.io/api/v1/models/MODEL_ID/variants/VARIANT_ID/decal-slots/SLOT_ID/logo-size' \
  -H "X-API-Key: $GLOSSI_API_KEY" \
  -H 'Content-Type: application/json' \
  -d '{ "logoWidthCm": 8, "logoHeightCm": 6 }'

Both sides must keep the artwork's proportions and fit inside the slot. Send both as null to go back to fitting the slot. The size belongs to that variant and slot only, and swapping the logo keeps its width while following the new artwork's proportions. The response is the assignment with its logoWidthCm and logoHeightCm.


A variant from start to finish

  1. GET /models/:modelId/decal-slots to learn the slots.
  2. POST /models/:modelId/variants with copyFromVariantId to start from an existing look.
  3. PUT /models/:modelId/variants/:variantId/decal-slots/:slotId to swap a logo.
  4. POST /projects/:projectId/variants, then POST /renders with variantsToRender to render it. For a second or third model in the project, PUT /projects/:projectId/variant-choices/:modelId sets the variant it wears in those renders.
  5. POST /models/:modelId/production-files/export to get the factory file.

On this page