📦 JavaScript SDK

Programmatic control of the 3D configurator for headless / React / Vue / Next.js apps. The SDK mounts the configurator in an iframe, resolves your shop SKUs to 3D products, and re-emits every widget event to your code.

SDK or embed.js?

embed.js (widget)sdk.js (this page)
SetupOne <script> tag, auto-detects the product on the pageYou instantiate a class and decide when/where to mount
Best forShopify, WooCommerce, CMS pages — turnkeySPAs, custom carts, dynamic product switching
ControlData attributes + a cart callbackFull API: mount, on/off, setProduct, destroy

If you just want the configurator on a product page with zero code, use the embed widget. If you build your own frontend and cart, use the SDK — the custom site guide shows a complete integration.

Installation

The SDK is a standard ES module served from our CDN — no npm package, no build step required:

import { PrintWearAI } from 'https://printwearai.com/sdk.js';

Loaded via a <script type="module"> tag, the class is also exposed as window.PrintWearAI for non-module code.

Initialization

const pwai = new PrintWearAI({ embedKey: 'fk_xxxx' });
OptionTypeDescription
embedKeystringRequired. Your public fk_ key (workspace → Integration). The constructor throws if missing.
originstringBase URL of the platform. Defaults to https://printwearai.com.

Never put your secret sk_ key in frontend code — the SDK only ever needs the public embed key. See Public REST API.

mount(selector, options)

Mounts the configurator iframe inside a container (CSS selector or DOM element). Returns a promise resolving to the instance. The container's previous content is replaced.

// By catalog slug
await pwai.mount('#configurator', { product: 'tshirt-classic-v1' });

// By shop SKU — resolved automatically via GET /api/resolve
await pwai.mount('#configurator', { sku: 'MY-SKU-42' });
OptionDescription
productProduct slug from your PrintWearAI catalog.
skuYour shop's SKU. Resolved through /api/resolve; mount throws if no 3D product is linked to it.
productIdYour shop's product ID (alternative to sku, same resolution).
configID of a saved configuration to preload.
heightInitial minimum iframe height in px. Default 700. The iframe then auto-resizes (never below 480 px).

If you pass neither product nor sku/productId, the widget opens on its product picker.

Events — on(event, fn) / off(event, fn)

The widget posts messages to the parent page; the SDK re-emits each message under its type. Both methods are chainable.

EventPayloadWhen
add_to_cartProduct info (incl. product.external_sku), quantity, pricingCustomer clicks "Add to cart" — wire this to your own cart.
resize{ height }Widget content height changed. The SDK already resizes the iframe for you; listen only if you need the value.
redirect{ url }The widget asks the host page to navigate (e.g. checkout).
pwai.on('add_to_cart', (payload) => {
  addToMyCart({ sku: payload.product.external_sku, qty: payload.quantity });
});

pwai.on('redirect', ({ url }) => { window.location = url; });

Listener exceptions are caught and logged to the console — one faulty handler will not break the others.

setProduct(slug)

Switches the mounted configurator to another catalog product without reloading the iframe:

pwai.setProduct('sweat-zip-v2');

destroy()

Removes the message listener, empties the container and clears all event listeners. Call it when your component unmounts (e.g. in a React useEffect cleanup); you can then reuse the instance with a new mount().

Complete example

<div id="configurator"></div>

<script type="module">
  import { PrintWearAI } from 'https://printwearai.com/sdk.js';

  const pwai = new PrintWearAI({ embedKey: 'fk_xxxx' });
  await pwai.mount('#configurator', { sku: 'MY-SKU-42', height: 760 });

  pwai
    .on('add_to_cart', ({ product, quantity }) => {
      myCart.add(product.external_sku, quantity);
    })
    .on('redirect', ({ url }) => { window.location = url; });

  // later: pwai.setProduct('shorts-pro-v1');  pwai.destroy();
</script>

See also