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.
| REST | MCP tool |
|---|---|
GET /models/:modelId/variants | list_model_variants |
POST /models/:modelId/variants | create_model_variant |
POST /models/:modelId/variants/:variantId/preview | request_variant_preview |
POST /projects/:projectId/variants | add_variants_to_project |
GET /projects/:projectId/variant-choices | get_project_variant_choices |
PUT /projects/:projectId/variant-choices/:modelId | set_project_variant_choice |
POST /renders with settings.variantsToRender | render with variantIds |
GET /models/:modelId/decal-slots | get_decal_slots |
PUT /models/:modelId/variants/:variantId/decal-slots/:slotId | set_decal_assignment |
PUT /models/:modelId/variants/:variantId/decal-slots/:slotId/logo-size | set_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"| Query | Default | |
|---|---|---|
limit | 50 | 1 to 100. |
after | nextCursor from the previous page. | |
search | Matches the variant's name, tags, and property values. Up to 200 characters. | |
purpose | PREPARED_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" }
]
}'| Field | Required | |
|---|---|---|
name | yes | Up to 80 characters. |
materialAssignments | unless copying | One entry per slot to set, up to 200. Slots you leave out keep the model's own material. |
copyFromVariantId | no | Start from what another variant of the same model wears, and its logos. materialAssignments override those slots. |
purpose | no | PREPARED_STYLE, STANDARD_COLORWAY or TEAM_DESIGN. A team design is copied from a STANDARD_COLORWAY and wears its materials. |
tagIds | no | Workspace 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 | |
|---|---|
PENDING | Being built. Usually a few minutes; poll the variants list until it changes. |
READY | The preview matches the variant. |
FAILED | The last build failed. Request it again. |
NEEDS_PROJECT | The model is in no project yet, so it cannot be loaded. Open it in the Studio once, then request it again. |
NONE | No 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.
Set or clear a logo
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.
Size a logo
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
GET /models/:modelId/decal-slotsto learn the slots.POST /models/:modelId/variantswithcopyFromVariantIdto start from an existing look.PUT /models/:modelId/variants/:variantId/decal-slots/:slotIdto swap a logo.POST /projects/:projectId/variants, thenPOST /renderswithvariantsToRenderto render it. For a second or third model in the project,PUT /projects/:projectId/variant-choices/:modelIdsets the variant it wears in those renders.POST /models/:modelId/production-files/exportto get the factory file.
Properties and asset search
Manage workspace properties and find assets by their values through the REST API or an MCP agent.
Production files
Generate numbered factory production files, keep their views current, and set the inks, decoration methods, and Pantones they print, through the REST API or an MCP agent.