Theme API reference

Ask about this Page
Copy for LLM
View as Markdown

The InStore Theming API endpoints let you read, replace, and partially update your tenant's POS theme, with request and response examples and notes on how each call affects the running InStore POS.

This page is the endpoint reference for the InStore Theming API.

Base path and methods

All theme operations act on a single resource path:

Theme resource pathbash
{mistApiBase}/{projectKey}/instore-tenants/{tenantId}/theme
The path placeholders (mistApiBase, projectKey, tenantId) and the required request headers are described in Run InStore POS API requests.
MethodPurposeRequired scope
GETRead the persisted theme.Open to any authenticated caller.
PUTReplace the whole theme. Fields you omit are unset.Administration.
PATCHApply a partial update via deep-merge.Administration.
Writes (PUT, PATCH) send a JSON body and require Content-Type: application/json.

How a request takes effect in the InStore POS

A theme write doesn't change the screen immediately. The InStore POS fetches the persisted theme at bootstrap, deep-merges it over the bundled default, and hands the result to MUI. A PUT or PATCH therefore takes effect on the next load of the POS. Reload to see your change.
Changes apply on the next POS load; they are not live. For the full merge model, see How overrides compose.

GET /theme

Returns the theme document stored for the tenant. It's read-only and has no effect on the running app. Inspect the active theme and use the response as the starting point for your next edit.

GET requestbash
GET {mistApiBase}/{projectKey}/instore-tenants/{tenantId}/theme

The response is the persisted theme document:

Response body examplejson
{
  "name": "My branded theme",
  "palette": {
    "text": { "primary": "#212121" },
    "primary": { "main": "#1976d2", "contrastText": "#ffffff" },
    "secondary": { "main": "#dc004e", "contrastText": "#ffffff" },
    "tertiary": { "main": "#4caf50", "contrastText": "#ffffff" },
    "background": { "default": "#fafafa" }
  },
  "typography": {
    "fontFamily": "Roboto, sans-serif",
    "h1": { "fontSize": "2.5rem", "fontWeight": 700, "lineHeight": 1.2 }
  },
  "spacing": 8,
  "shape": { "borderRadius": 4 },
  "components": {
    "MuiButton": {
      "defaultProps": { "disableElevation": true },
      "styleOverrides": {
        "root": {
          "borderRadius": "8px",
          "textTransform": "none",
          "&.Mui-disabled": {
            "backgroundColor": "action.disabledBackground",
            "color": "action.disabled"
          }
        }
      }
    }
  },
  "customTokens": {
    "layout": { "mobileFooter": { "xs": true, "md": false } },
    "sidebar": { "showCollapseButton": true }
  }
}

Effect on the app: none. Nothing re-renders.

Run GET before each change and use its response as the base for your next PUT or PATCH. The InStore POS stores only the currently active theme and keeps no server-side version history. commercetools cannot recover a configuration you overwrite. To avoid losing a working configuration, see Back up your theme payloads.

PUT /theme

Replaces the entire theme in one call. Any top-level field you don't send is unset.

PUT requestbash
PUT {mistApiBase}/{projectKey}/instore-tenants/{tenantId}/theme
{
  "name": "My branded theme",
  "palette": {
    "primary": { "main": "#1976d2", "contrastText": "#ffffff" },
    "secondary": { "main": "#dc004e", "contrastText": "#ffffff" },
    "tertiary": { "main": "#4caf50", "contrastText": "#ffffff" }
  },
  "typography": { "fontFamily": "Roboto, sans-serif" },
  "spacing": 8,
  "shape": { "borderRadius": 4 },
  "components": {
    "MuiButton": {
      "defaultProps": { "disableElevation": true },
      "styleOverrides": { "root": { "borderRadius": "8px" } }
    }
  },
  "customTokens": {
    "layout": { "mobileFooter": { "xs": true, "md": false } },
    "sidebar": { "showCollapseButton": true }
  }
}
A successful PUT returns the persisted theme, which is the same body you sent, normalized.
Effect on the app: re-skins the whole POS on the next load. Sending an empty or absent body reverts the tenant to the Default theme, which resembles the legacy InStore look. To compare the fallback theme with the starter theme, see Default and POS starter themes.

PATCH /theme

Applies a partial update. Leaf values are deep-merged into the stored theme, so you only send what changes, except a components.MuiX block, which is replaced atomically.

Scenario 1: change only the sidebar's responsive layout.

PATCH request: sidebar onlybash
PATCH {mistApiBase}/{projectKey}/instore-tenants/{tenantId}/theme
{
  "customTokens": {
    "sidebar": {
      "showCollapseButton": { "xs": true, "md": false }
    }
  }
}
The response shows the merged result: customTokens.sidebar.showCollapseButton is updated and everything else is preserved.

Scenario 2: replace a single component override.

PATCH request: replace MuiButtonbash
PATCH {mistApiBase}/{projectKey}/instore-tenants/{tenantId}/theme
{
  "components": {
    "MuiButton": {
      "defaultProps": { "disableElevation": true },
      "styleOverrides": {
        "root": {
          "borderRadius": "8px",
          "&.Mui-disabled": {
            "backgroundColor": "action.disabledBackground",
            "color": "action.disabled"
          }
        }
      },
      "variants": [
        {
          "props": { "className": "instore-primary-action" },
          "style": {
            "backgroundColor": "primary.main",
            "color": "primary.contrastText",
            "&:hover": { "backgroundColor": "primary.dark" }
          }
        }
      ]
    }
  }
}
The style values reference palette tokens such as primary.main, the derived primary.dark, and the semantic MUI action.* tokens, rather than hard-coded hex. To understand which token strings are supported and when derived shades are available, see Reference palette tokens in component overrides.

Scenario 3: move the sidebar to the left or right.

The InStore POS reads which side the sidebar docks on from components.MuiDrawer.defaultProps.anchor. The bundled POS theme docks it on the right ("anchor": "right"); set it to "left" to move the sidebar (and the surrounding page layout, which flips to match) to the left. Only "left" and "right" are meaningful for the POS sidebar.
PATCH request: move the sidebar to the leftbash
PATCH {mistApiBase}/{projectKey}/instore-tenants/{tenantId}/theme
{
  "components": {
    "MuiDrawer": {
      "defaultProps": { "anchor": "left" }
    }
  }
}
anchor is the only field that changes the side, but a components.MuiX block is replaced atomically. A MuiDrawer payload that carries only defaultProps drops the bundled sidebar styleOverrides and its responsive variants, which breaks the sidebar's appearance. Run GET /theme first, change defaultProps.anchor inside the returned MuiDrawer block, then send the whole block back.
When you PATCH any components.X entry, the entire block under that component is replaced. Sibling components (for example, MuiFormControl) are preserved, but the MuiButton inner defaultProps, styleOverrides, and variants are not deep-merged. Send the full block if you want to keep existing properties.
Effect on the app: changes only the surfaces you targeted. Because a components.MuiX block is replaced wholesale, omitting slots you previously set will visibly drop those styles. Resend the full block to keep them.

PUT vs PATCH at a glance

PUTPATCH
Top-level fields you omitUnsetPreserved
Leaf values you sendReplaceDeep-merged
A components.MuiX block you sendReplaces the whole blockReplaces the whole block (atomic)
Empty or absent bodyReverts to the Default themeNo-op
Use it toSet or reset the whole themeTweak specific values

Theme payload fields

The theme document is the MUI ThemeOptions shape plus a small set of InStore-specific fields. The top-level fields are summarized below; for what each one controls and how to author it, follow the links into Customize POS styles and behavior. Inside components, color values resolve as MUI sx, so reference palette tokens such as 'primary.main' instead of repeating hex. To choose valid token strings and avoid hard-coded color values, see Reference palette tokens in component overrides. To find which components.MuiX block and customTokens flag drives a given on-screen surface, see the POS style reference.
FieldTypeDescription
nameStringHuman-readable identifier for the theme.
paletteObjectColor tokens: primary, secondary, tertiary, text, background. Mirrors MUI palette.
typographyObjectFont scale: fontFamily, h1 to h6, body1, body2, and other variants. Mirrors MUI typography.
breakpointsObjectResponsive breakpoint thresholds. To understand the breakpoint keys and values, see MUI breakpoints.
spacingNumber | Number[]MUI spacing unit.
shapeObjectGeometry tokens: for example, borderRadius.
componentsObjectPer-MUI-component overrides. To author slots, variants, and default props, see Customize MUI component overrides.
customTokensObjectPOS-specific responsive layout flags. To change responsive POS layout behavior, see Responsive layout tokens.

Validation and errors

The API accepts JSON only and enforces a strict schema. Writes are rejected with 400 when they break these rules:
  • String values: max 512 characters; forbidden characters <, >, backtick, \r, \n. The applied regular expression (with the backtick shown as BT) is ^[^<>BT\r\n]*$.
  • Colors: any string MUI accepts (for example, #15375C, rgba(0,0,0,0.87), hsl(210, 50%, 45%), or named colors). Strings are passed through unchanged.
  • __fn allowlist: only { "__fn": "ownerState", "cases": { ... } } is accepted, with no other discriminator value and no inline function literals. To define conditional styles from supported ownerState values, see The ownerState escape hatch.
  • Unknown fields are rejected at every nesting level.
Validation error response examplejson
{
  "statusCode": 400,
  "message": "Expected SafeCssString but got string with forbidden character",
  "errors": [
    {
      "code": "InvalidInput",
      "message": "Forbidden character at index 8",
      "path": "$input.palette.primary.main"
    }
  ]
}