SudoMock
API

Studio

Embed a live mockup editor in your storefront via iframe. Your server creates a session, your page embeds the editor with the returned token, and your page listens for postMessage events. The same flow powers both PSD customization and 2D product photo mockups.

Studio is the shared editor for both PSD templates and 2D mockups. One iframe, both engines. Your customers design on your storefront, and you never build a rendering pipeline.

The Studio editor embedded on a storefront: a customer adjusts artwork on a product, then adds it to cart.
The Studio editor, embedded on your storefront. Your customer customizes, then adds to cart.
Render API
Server-side rendering. Send a request, get a hosted image back. Feeds Render (PSD) and Render (2D).
Studio (embed)
A drop-in iframe editor. Your customers design on your site, with no render pipeline to build. You are here.
White-label
Studio with your branding, labels, and panels. See White-label configuration.
Drop it in with one iframe
One <iframe> and a short-lived session. The customizer stays embedded on your product page and is bound to that page's exact origin.
No backend to build
Your server makes one create-session call. Upload, placement, live preview, and the finished image are all handled inside Studio.
Fully customizable
Colors, labels, and which controls appear are a documented config contract, not guesswork. See White-label configuration.
White-label
Your logo, your accent color, your button text, light or dark. The editor reads as part of your own product.

The integration contract, in three parts

Studio is a module, not a screenshot. Your page talks to it through three documented surfaces: the create-session call that mints the token, the postMessage events and origin-proof handshake it exchanges with your page, and the white-label config that skins it.

Studio lets your customers customize a mockup directly on your storefront, without leaving your page. It comes in two flavors that share the same integration shape:

PSD customizationmockup_type: psd

Open an iframe editor for a prepared PSD template. Bind the session to an existing mockup_uuid and the exact allowed_origin that embeds it.

2D product photomockup_type: 2d

Open the 2D customizer for a product photo mockup. Use setup for full editing access or customize for shoppers working on a ready mockup.

Both are created through the same POST /studio/create-session endpoint and both return an opaque session token for the iframe plus one-time handshake values for the trusted parent page. Only the session token belongs in the iframe URL.

POST/api/v1/studio/create-session
x-api-key / Shopify HMAC

API Key Never Exposed

Session tokens are opaque (sess_ + random characters). Your API key is stored server-side and never included in the token or any client response. Successful use refreshes the idle window, bounded by a four-hour absolute expiry.

How It Works

Two 2D session kinds

setup: create or open a mockup with full editing access, including product selection, print areas, artwork placement, preview, render, and save.

customize: bind a ready mockup_uuid. The shopper can place artwork, preview, render, and submit, but cannot edit the product selection or print areas.

The typical storefront flow: prepare the mockup with a setup session or the public 2D Mockups API, then open a customize session on that mockup_uuid with a product_id for every shopper.
1
Your server creates a session
Call POST /studio/create-session with your API key (server-to-server). The API verifies ownership and generates an opaque token for one customization session.
2
Pass the token to the client
Send only the sess_xxx token to your frontend. The API key stays on your server.
3
Open Studio with the session
Load studio.sudomock.com/editor?session=sess_xxx in an iframe. The editor verifies the token, proves the parent origin, and loads the merchant config.
4
Listen for events
Subscribe to window message events. Setup returns studio.mockup-saved; customize returns studio.design-submitted. The editor also reports ready, close, and error events.
5
Activity refreshes the idle window
Successful use refreshes the idle expiry, up to the session's four-hour absolute limit.

Setup opens the full editor

setup is a permission profile, not a sequence of stages. Studio prepares a new product automatically and opens the full editor with product editing, print-area editing, artwork placement, preview, render, and save available together.

Customize keeps administrative controls unavailable

A customize session opens the same editor surface for a ready mockup_uuid, but it grants only artwork placement, preview, render, and submit. Labels and colors can change presentation; they never change these permissions.

Authentication

Studio endpoints use three authentication schemes depending on the endpoint and caller:

SchemeHeader / MechanismUsed By
API Keyx-api-key: sm_your_api_keyCreate and confirm Studio sessions from your server
Shopify HMACShopify App Proxy signature (query params)create-session (Shopify storefronts via App Proxy)

POST /create-session

Generates an opaque session token for the Studio editor. Requires x-api-key header (WooCommerce, custom integrations) or Shopify App Proxy HMAC signature. The API key never leaves the server. One endpoint serves both mockup types, distinguished by the request body.

Headers

x-api-keystring

Your SudoMock API key starting with sm_. Required unless using Shopify HMAC authentication. Used server-side only. Never expose it to the browser.

Content-TypestringRequired

Must be application/json

Request Body: PSD customization session

Bind the session to a prepared PSD-backed mockup by its mockup_uuidand embed it from the exact allowed_origin.

mockup_uuidstringRequired

UUID of the mockup to open in Studio. Must belong to the authenticated account.

allowed_originstringRequired

The exact origin of the page that embeds the Studio iframe, for example https://shop.example.com.

product_idstring

Product identifier from your platform (e.g., Shopify Product GID, WooCommerce product ID). Stored in the session for your reference.

variant_idstring

Optional variant identifier. Send the same value in the server-side result confirmation.

configobject

Optional configuration for this session. It accepts the same partial fields listed under Studio Configuration, without config_version. The override is not saved and requires x-api-key authentication.

Request Body: PSD customization
1{
2 "mockup_type": "psd",
3 "session_kind": "customize",
4 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
5 "allowed_origin": "https://shop.example.com",
6 "product_id": "gid://shopify/Product/123456",
7 "variant_id": "gid://shopify/ProductVariant/789",
8 "action_id": "add-to-cart",
9 "config": {
10 "theme": "dark",
11 "accentColor": "#3366FF",
12 "psdPrimaryActionLabel": "Add to cart"
13 }
14}

Request Body: 2D product photo session

Open the 2D customizer for a product photo mockup. Set mockup_type to 2d and choose a session_kind. The editor always runs in an iframe embedded by allowed_origin. If your mockup is already prepared and you only want placement and rendering, use customize; product and print-area controls stay unavailable.

What you wantsession_kindAccess
Create or edit a mockupsetupFull editing, placement, render, and save
Use a ready mockup in a storefrontcustomizeArtwork placement, render, and submit
mockup_typeenumRequired

Set to 2d for the 2D customizer.

session_kindenumRequired

One of setup or customize. Use setup for full editing access. Use customize for a shopper working on a ready mockup_uuid.

allowed_originstringRequired

The exact origin of the page that will embed the iframe (for example https://shop.example.com). The customizer only runs when it is embedded by this origin.

product_idstring

Optional product identifier from your platform. Use it to associate the session with your catalog.

variant_idstring

Optional variant identifier. Send the same value in the server-side result confirmation.

mockup_uuidstring

Required for customize. Optional for setup, where omitting it starts a new mockup. Must be a valid UUID.

action_idstring

Optional allowlisted routing identifier returned with the result event. Use 1–64 characters from A–Z, a–z, 0–9, dot, underscore, colon, and hyphen.

configobject

Optional configuration for this session. It accepts the same partial fields listed under Studio Configuration, without config_version. Omitted fields use the API key's saved settings. Send null for one field to use its theme default for this session. The override is not saved.

Configuration never grants permissions

Session configuration is accepted only on server-to-server x-api-keyrequests. It can change appearance, labels, and optional controls, but cannot change the session kind or grant setup capabilities.
Request Body: 2D storefront customize (shopper on a pre-built mockup)
1{
2 "mockup_type": "2d",
3 "session_kind": "customize",
4 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
5 "allowed_origin": "https://shop.example.com",
6 "product_id": "SKU-1234",
7 "variant_id": "SKU-1234-BLACK-M",
8 "action_id": "add-to-cart",
9 "config": {
10 "theme": "dark",
11 "accentColor": "#3366FF",
12 "twoDCustomizePrimaryActionLabel": "Add to cart"
13 }
14}
Request Body: 2D setup (new mockup)
1{
2 "mockup_type": "2d",
3 "session_kind": "setup",
4 "allowed_origin": "https://shop.example.com",
5 "product_id": "SKU-1234",
6 "variant_id": "SKU-1234-BLACK-M",
7 "action_id": "save-mockup",
8 "config": {
9 "theme": "light",
10 "accentColor": "#3366FF",
11 "twoDSetupPrimaryActionLabel": "Save mockup"
12 }
13}

A pre-built mockup is ready for a customize session

A 2D mockup built through the public 2D Mockups API (or saved with a setup session) returns a mockup_uuidthat can be used to create a customize session. The shopper opens directly in artwork placement without administrative controls.

Response

200OK

Every response includes mockup_type, an opaque session, and expires_in. Both PSD and 2D responses return the credentials required by the origin-proof message handshake.

Response: PSD customization session
1{
2 "success": true,
3 "mockup_type": "psd",
4 "session": "sess_3_TU1FyqABbmj28yg_-YqENaK-CnvsxBuovgmiT_RHc",
5 "expires_in": 900,
6 "message_session_id": "fac13800-0273-4ea6-aef6-56c818383f0d",
7 "bootstrap_secret": "dtiinV-YkyuD35zTViO2RIBHM4xNCaDJMXC2C4qiPN4"
8}
Response: 2D product photo session
1{
2 "success": true,
3 "mockup_type": "2d",
4 "session": "sess_9adcc8281f4e4a2b9c3d2e6f8b0a1d77",
5 "expires_in": 1800,
6 "message_session_id": "fac13800-0273-4ea6-aef6-56c818383f0d",
7 "bootstrap_secret": "dtiinV-YkyuD35zTViO2RIBHM4xNCaDJMXC2C4qiPN4"
8}
successbooleanRequired

Always true on success. Errors return HTTP exceptions.

sessionstringRequired

Opaque session token. Format: sess_ followed by URL-safe random characters. Pass this to the Studio URL. It carries no API key. Create a fresh session per customization; do not cache or reuse tokens across customers.

expires_inintegerRequired

Initial idle lifetime in seconds: 1,800 for setup and 900 for customize. Successful use refreshes the idle window, bounded by the four-hour absolute expiry.

mockup_typestringRequired

Echoes psd or 2d.

message_session_idstringRequired

Bind every postMessage envelope to this session identifier.

bootstrap_secretstringRequired

Deliver to the trusted parent page for the origin-proof handshake. Never put it in the iframe URL or logs.

Studio is iframe-only

Both PSD and 2D sessions run inside an iframe bound to allowed_origin. Popup and top-level page modes are not supported because they cannot complete the parent-origin handshake.

Error Responses

400Bad Request

A required field is missing or a value is invalid: for example, a customize request without a mockup_uuid, an unsupported session kind, or a malformed origin.

json
1{
2 "success": false,
3 "error": {
4 "code": "INVALID_SESSION_REQUEST",
5 "message": "mockup_uuid is required for a customize session.",
6 "retryable": false
7 }
8}
401Unauthorized
json
1{
2 "success": false,
3 "error": {
4 "code": "AUTHENTICATION_FAILED",
5 "message": "The API key is invalid or inactive.",
6 "retryable": false
7 }
8}

The API key is invalid or has been deactivated. Signed Shopify requests return a standard detail response when the HMAC signature is missing, invalid, or expired.

403Forbidden
json
1{
2 "success": false,
3 "error": {
4 "code": "MOCKUP_NOT_AVAILABLE",
5 "message": "The mockup is not available for this account.",
6 "retryable": false
7 }
8}

The requested 2D mockup is unavailable to this account. UI overrides on a non-2D or non-API-key session also return a structured 403 response. PSD ownership failures use a standard detail response.

404Not Found
json
1{
2 "success": false,
3 "error": {
4 "code": "STORE_NOT_CONNECTED",
5 "message": "The store is not connected.",
6 "retryable": false
7 }
8}

Shopify HMAC flow only: the shop domain is not linked to any SudoMock account.

409Conflict
json
1{
2 "success": false,
3 "error": {
4 "code": "SETUP_REQUIRED",
5 "message": "The mockup setup must be finalized before customization.",
6 "retryable": false
7 }
8}

A customize session was requested before its 2D mockup was ready for shopper use. Finish the mockup in a setup session, then create a new customize session.

Code Examples

Call this endpoint from your backend so your API key stays server-side. The trusted parent page needs message_session_id and bootstrap_secretfor the origin-proof handshake. Put only the session token in the iframe URL and never log the bootstrap secret.

Create a PSD customization session
bash
1curl -X POST "https://api.sudomock.com/api/v1/studio/create-session" \
2 -H "Content-Type: application/json" \
3 -H "x-api-key: sm_your_api_key" \
4 -d '{
5 "mockup_type": "psd",
6 "session_kind": "customize",
7 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
8 "allowed_origin": "https://shop.example.com",
9 "product_id": "product-123",
10 "variant_id": "variant-456",
11 "action_id": "add-to-cart"
12 }'
Create a 2D storefront customize session (shopper flow)
bash
1curl -X POST "https://api.sudomock.com/api/v1/studio/create-session" \
2 -H "Content-Type: application/json" \
3 -H "x-api-key: sm_your_api_key" \
4 -d '{
5 "mockup_type": "2d",
6 "session_kind": "customize",
7 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
8 "allowed_origin": "https://shop.example.com",
9 "product_id": "SKU-1234",
10 "variant_id": "SKU-1234-BLACK-M"
11 }'

Use setup when an administrator needs the complete editor. Omit mockup_uuid to create a new mockup, or provide it to edit an existing one.

Create a 2D setup session
bash
1curl -X POST "https://api.sudomock.com/api/v1/studio/create-session" \
2 -H "Content-Type: application/json" \
3 -H "x-api-key: sm_your_api_key" \
4 -d '{
5 "mockup_type": "2d",
6 "session_kind": "setup",
7 "allowed_origin": "https://shop.example.com",
8 "product_id": "SKU-1234",
9 "variant_id": "SKU-1234-BLACK-M"
10 }'

Embed the iframe

Load the customizer with the session token you just created. Size the iframe to fit your layout; the editor is responsive inside it.

Embed the customizer
1<iframe
2 id="sudomock-studio"
3 src="https://studio.sudomock.com/editor?session=SESS_TOKEN"
4 allow="clipboard-write"
5 style="width: 100%; height: 720px; border: 0; border-radius: 12px;"
6 title="Customize your product"
7></iframe>

Origin must match

The page that hosts the iframe must be served from the exact allowed_origin you sent when creating the session. If they differ, the customizer will not start.

postMessage Event Protocol

The embedded editor communicates with your page through the browser postMessage API. Add a single message listener on your page. Every message the editor sends is an object with a source of sudomock-studio, a type naming the event, and a payload with the event data.

Always verify the sender

Check the exact origin, event.source === iframe.contentWindow, protocol version, expected message_session_id, and a replay set keyed by request_id. An origin check alone is not enough when a page has more than one Studio frame.

Event Reference

typeWhen it firesPayload fields
studio.readyThe customizer has loaded and is interactive.protocol_version
studio.mockup-savedThe primary action is used in a setup session.mockup_uuid, render_uuid, action_id?
studio.design-submittedThe primary action is used in a customize session.mockup_uuid, render_uuid, action_id?
studio.closeThe customer closed the customizer.reason (completed | cancelled)
studio.errorSomething went wrong during the session.code, message, retryable

Result Events

Setup emits studio.mockup-saved; customize emits studio.design-submitted. Both carry only stable identifiers needed for integration. Forward the event to your server, confirm it with POST /api/v1/studio/actions/consume, use action_id to route the confirmed result to your own allowlisted action, then acknowledge it with parent.action-result. URLs, session tokens, API keys, proof keys, and source artwork are never callback fields.

A browser event is not an authorization result

Never add a cart line or save a product from the browser payload alone. Your server must call POST /api/v1/studio/actions/consume with its API key. The endpoint binds the event to the merchant, session, and successful render, then returns the same receipt for an exact retry.
mockup_uuidstring

The mockup template this result was produced from.

render_uuidstring

Identifies this exact customized result. Store it on the cart line so the order references the right output.

action_idstring

Optional allowlisted routing identifier supplied when the session was created.

studio.design-submitted message
1{
2 "version": 1,
3 "source": "sudomock-studio",
4 "type": "studio.design-submitted",
5 "request_id": "9b6964ec-b2d3-4c06-86e8-188875cb43ad",
6 "message_session_id": "fac13800-0273-4ea6-aef6-56c818383f0d",
7 "payload": {
8 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
9 "render_uuid": "9adcc828-1f4e-4a2b-9c3d-2e6f8b0a1d77",
10 "action_id": "add-to-cart"
11 }
12}

Confirming a Result on Your Server

Send the event envelope without its browser-only source field. Add action_context from your authenticated server state, not from browser input. Its product and variant values must exactly match the values bound when the session was created. The API key stays on your server.

POST /api/v1/studio/actions/consume
1{
2 "version": 1,
3 "type": "studio.design-submitted",
4 "request_id": "9b6964ec-b2d3-4c06-86e8-188875cb43ad",
5 "message_session_id": "fac13800-0273-4ea6-aef6-56c818383f0d",
6 "payload": {
7 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
8 "render_uuid": "9adcc828-1f4e-4a2b-9c3d-2e6f8b0a1d77",
9 "action_id": "add-to-cart",
10 "action_context": {
11 "product_id": "SKU-1234",
12 "variant_id": "SKU-1234-BLACK-M"
13 }
14 }
15}
Confirmed action receipt
1{
2 "success": true,
3 "replayed": false,
4 "receipt": {
5 "version": 1,
6 "request_id": "9b6964ec-b2d3-4c06-86e8-188875cb43ad",
7 "message_session_id": "fac13800-0273-4ea6-aef6-56c818383f0d",
8 "type": "studio.design-submitted",
9 "mockup_type": "2d",
10 "session_kind": "customize",
11 "action_id": "add-to-cart",
12 "action_context": {
13 "product_id": "SKU-1234",
14 "variant_id": "SKU-1234-BLACK-M"
15 },
16 "mockup_uuid": "c315f78f-d2c7-4541-b240-a9372842de94",
17 "render_uuid": "9adcc828-1f4e-4a2b-9c3d-2e6f8b0a1d77"
18 }
19}

Listening for Events

A single listener handles the whole protocol. Route on message.type and act on the ones your integration needs.

postMessage listener
1const STUDIO_ORIGIN = "https://studio.sudomock.com";
2const studioFrame = document.querySelector("#sudomock-studio");
3const expectedMessageSessionId = createSessionResponse.message_session_id;
4const seen = new Set();
5
6// bootstrapSecret is the bootstrap_secret from your server's create-session response.
7// Deliver it only to this trusted parent page; never put it in the iframe URL or logs.
8// It is relayed to the editor only in the handshake below. A fresh 22-char base64url nonce:
9const nonce = () =>
10 btoa(String.fromCharCode(...crypto.getRandomValues(new Uint8Array(16))))
11 .replace(/\+/g, "-").replace(/\//g, "_").replace(/=+$/, "");
12
13window.addEventListener("message", async (event) => {
14 if (event.origin !== STUDIO_ORIGIN || event.source !== studioFrame.contentWindow) return;
15
16 const message = event.data;
17 if (
18 !message ||
19 message.version !== 1 ||
20 message.source !== "sudomock-studio" ||
21 message.message_session_id !== expectedMessageSessionId ||
22 typeof message.request_id !== "string" ||
23 seen.has(message.request_id)
24 ) return;
25 seen.add(message.request_id);
26
27 switch (message.type) {
28 case "studio.ready":
29 // REQUIRED origin-proof handshake: reply so the editor can open. Skip this and the
30 // customizer stays on "The customizer could not be opened." bootstrapSecret comes
31 // from your create-session response; child_nonce is echoed back verbatim.
32 event.source.postMessage({
33 version: 1,
34 source: "sudomock-parent",
35 type: "parent.bootstrap",
36 request_id: message.request_id,
37 message_session_id: message.message_session_id,
38 payload: {
39 child_nonce: message.payload.child_nonce,
40 parent_nonce: nonce(),
41 bootstrap_secret: bootstrapSecret,
42 },
43 }, STUDIO_ORIGIN);
44 break;
45
46 case "studio.mockup-saved":
47 case "studio.design-submitted": {
48 const p = message.payload;
49 const { source: _source, ...actionEvent } = message;
50 const response = await fetch("/api/studio/action", {
51 method: "POST",
52 headers: { "content-type": "application/json" },
53 body: JSON.stringify({ event: actionEvent }),
54 });
55 const success = response.ok;
56 if (!success) seen.delete(message.request_id);
57 event.source.postMessage({
58 version: 1,
59 source: "sudomock-parent",
60 type: "parent.action-result",
61 request_id: message.request_id,
62 message_session_id: expectedMessageSessionId,
63 payload: { render_uuid: p.render_uuid, success },
64 }, STUDIO_ORIGIN);
65 break;
66 }
67
68 case "studio.close":
69 // The customer closed the customizer (reason: completed | cancelled).
70 closeCustomizerModal();
71 break;
72
73 case "studio.error":
74 // Something went wrong. retryable tells you if a retry may help.
75 console.error(message.payload.code, message.payload.message);
76 break;
77 }
78});

Make it yours

Your logo, your colors, your buttons, your theme. It looks like part of your store, not a plugin. Set each through the config below. See White-label configuration for the full key reference.

Studio Configuration

Store the default appearance and controls per API key with GET /api/v1/studio/config and PUT /api/v1/studio/config. Both calls require your x-api-key header and belong on your server. The same settings are available in Dashboard → Studio settings.

MethodBehavior
GET /api/v1/studio/configReturns the complete effective configuration and its config_version.
PUT /api/v1/studio/configSends config_version plus a partial config. Send null to reset one override to its default.

Updates are versioned

Use the latest config_version returned by GET or PUT. A stale write returns 409 without changing the saved configuration.
PUT /api/v1/studio/config
1{
2 "config_version": 4,
3 "config": {
4 "theme": "light",
5 "accentColor": "#DA7756",
6 "psdPrimaryActionLabel": "Add to Cart",
7 "twoDSetupPrimaryActionLabel": "Save Mockup",
8 "twoDCustomizePrimaryActionLabel": "Add to Cart",
9 "twoDShowExport": false
10 }
11}
Effective configuration response
1{
2 "config_version": 5,
3 "config": {
4 "theme": "light",
5 "primaryColor": "#0F172A",
6 "accentColor": "#DA7756",
7 "backgroundColor": "#F1F5F9",
8 "panelBackground": "#FFFFFF",
9 "textColor": "#0F172A",
10 "borderColor": "#E2E8F0",
11 "successColor": "#16A34A",
12 "borderRadius": 10,
13 "logoUrl": null,
14 "fontFamily": null,
15 "headerText": "Customize Your Design",
16 "uploadText": "Drop image or click to upload",
17 "loadingText": "Adding...",
18 "successText": "Added!",
19 "secondaryActionLabel": "Render Preview",
20 "psdPrimaryActionLabel": "Add to Cart",
21 "twoDSetupPrimaryActionLabel": "Save Mockup",
22 "twoDCustomizePrimaryActionLabel": "Add to Cart"
23 }
24}

Shared branding and labels

KeyDefaultWhat it controls
themelightLight or dark base palette. Explicit colors take precedence.
primaryColor#0F172APrimary UI color.
accentColor#DA7756Actions and selected states.
backgroundColor#F1F5F9Editor page background.
panelBackground#FFFFFFEditor panel background.
textColor#0F172AEditor text.
borderColor#E2E8F0Borders and dividers.
successColor#16A34ASuccessful final action.
borderRadius10Corner radius from 0 to 20 pixels.
logoUrlnullHTTPS logo URL.
fontFamilynullFont family or fallback list.
headerTextCustomize Your DesignEditor heading. Empty hides it.
uploadTextDrop image or click to uploadUpload prompt.
loadingTextAdding...Final-action loading state.
successTextAdded!Final-action success state.
secondaryActionLabelRender PreviewPSD preview action.
maxFileSize15Maximum PSD and 2D upload size in MB, from 1 to 50.

PSD Editor settings

KeyDefaultWhat it controls
psdPrimaryActionLabelAdd to CartFinal action label.
psdShowAdjustmentstrueAdjustment controls.
psdShowColorOverlaytrueColor overlay controls.
psdShowTextLayerstrueEditable text layer controls.
psdShowFitModetrueArtwork fit choices.
psdShowPositiontruePosition controls.
psdShowSizetrueSize controls.
psdShowRotationtrueRotation control.
psdShowFliptrueFlip actions.
psdShowExportOptionstrueFormat, size, and quality controls.
psdShowZoomControlstrueCanvas zoom controls.
psdShowUndoRedotrueUndo and redo.
psdAutoRendertrueRender after edits settle.
psdAutoRenderDelay800Auto-render delay from 300 to 3000 ms.
psdLayoutfullFull or compact layout.

2D Mockups settings

KeyDefaultWhat it controls
twoDSetupPrimaryActionLabelSave MockupFinal action label in setup sessions.
twoDCustomizePrimaryActionLabelAdd to CartFinal action label in customize sessions.
twoDShowArtworktrueArtwork upload and replacement.
twoDShowFilltrueSolid fill control. Artwork or fill must remain available.
twoDShowBlendtrueBlend choices.
twoDShowOpacitytrueArtwork opacity.
twoDShowTransformtruePosition, size, and rotation controls.
twoDShowZoomtrueCanvas zoom controls.
twoDShowExporttruePreview download action.
twoDShowBackgroundRemovaltrueBackground removal when the session allows it.

To adapt one iframe to the parent page's current theme, send a partial config in POST /api/v1/studio/create-session. It accepts the same keys above, does not use config_version, and is not saved. Omitted keys keep the API key's saved settings; null restores that field's theme default for this session.

Capabilities stay server-controlled

Hiding or renaming a control never changes what the session may do. Setup-only selection and print-area controls are not configuration options: they appear whenever a setup session is allowed to use them, and remain unavailable in customize sessions.

Security Model

Studio sessions are designed with a zero-trust approach to API key protection:

API key never leaves the server
Stored server-side and never included in the token or any client response. create-session is the only call that needs it.
Opaque tokens are not decodable
Session tokens are cryptographically random, opaque strings, not JWTs. No sensitive data is embedded.
Mockup ownership enforced
Each session is locked to a specific mockup at creation. The session cannot be used to access other mockups.
Origin binding (2D sessions)
Each 2D session is tied to the allowed_origin you set. The customizer runs only when embedded by that origin, so a leaked token cannot be embedded elsewhere.
Idle and absolute expiry
Inactive sessions expire automatically. Successful use refreshes the idle window, but every session still ends at its four-hour absolute expiry.
Shopify HMAC replay protection
Shopify App Proxy requests are verified via HMAC-SHA256 signature and rejected if older than 5 minutes.
Presentation cannot grant permissions
Session UI values only affect labels and color. The server controls every setup and customize capability.

Shopify and WooCommerce

The pattern is identical on hosted platforms. Create the session from your platform backend so the API key stays server-side, then embed the iframe on the product page and route the result event to your platform backend.

Shopifypattern

Create the session from your app backend, bind action_id to an allowlisted cart action, and resolve the returned render_uuid on your server before adding the line item.

WooCommercepattern

Create the session from PHP on your server, bind action_id to an allowlisted cart action, and store the returned render_uuid in cart-item metadata.