Articles on: API

3D Viewer - API documentation

3D Viewer API

The sayduck viewer exposes an api object with various methods that you can use to interact with the sayduck viewer. There are two methods to access the viewer api.

Listen for the sayduck.api-ready event (Recommended)¨

let api;

window.addEventListener('sayduck.api-ready', (event) => {
    api = (event as CustomEvent).detail.instance;

Invoke the sayduck.request-api event

async function getViewerApi() {

  const request = new CustomEvent('sayduck.request-api', {
    bubbles: true,
    composed: true,
    detail: {
      instance: {},

  const api = await request.detail.instance;
  return api;

glTF Loaded

Sent when the 3D Viewer has finished loading.

Variants API

Functionality related to variants is available on the configurator (api.variants) property of the api and is only available when viewer mode attribute is set to variants.

<sayduck-viewer product="product-uuid" 

Change variant

Set active variant to input.

List variant UUIDs

List all variant uuids, names and metadata.

Configurator API

Functionality related to configurator is available on the configurator (api.configurator) property of the api and is only available when viewer mode attribute is set to configurator.

<sayduck-viewer product="product-uuid" 

Get configuration values

api.configurator.getConfigurations(): ConfigurationObject[]
Lists all the configuration and it's variants/configurations and their children, useful when creating a custom picker.

export interface ConfigurationObject {

  uuid: string;
  name: string;
  label: string | null;
  children?: ConfigurationObject[];
  isOptional?: boolean;
  isConfiguration?: boolean;
  parent: {
    uuid: string;
    name: string;
  } | null;
  selectedVariant?: {
    uuid: string | null;
    name: string | null;

Change variant / configuration

api.configurator.setActiveByUuid("variant-uuid" | "configuration-uuid");
Note: Setting a configuration uuid instead of the variant will select the first variant of that configuration

List selected variants

List selected variant uuids, names and metadata.

List selected variant uuids

List selected variants uuids.

Disable optional configuration

Disable configuration that is marked optional.

Create a simple picker

api.configurator.createPicker(): HTMLElement
This will create a simple picker with buttons that change the variants. The elements themselves won't have any styling, you need to style them for yourself. If you want more control over how the picker works/looks it's recommended to create your own picker.

Here's a list of classes of the elements created:

sayduck-picker - Container element
sayduck-configuration - Configuration
sayduck-configuration-label - Configuration label
sayduck-variant-button - Variant button
sayduck-variant-button-active - Variant active

Scene API

Functionality related to scene is available on the configurator (api.scene) property of the api and is only available for both viewer mode attribute configurator & variants .

Load new product without reloading page

api.scene.update3dViewer(productUuid: string, mode: APP_MODE);
Load new product without reloading page.

Augmented reality (AR)

Launch AR (menu)

Launch AR on the active scene when trigged on mobile.

Request QR code URL

Requests QR code URL that can then be used to integrate custom QR code elements.


Toggle dimensions (menu)

Triggers Dimensions in the action menu.

Load dimensions on selected configurations

The new function expects an array of configurations UUIDS and it returns the dimensions of the selection.

Optionally showDimensionsInViewer can be passed, making the output dimensions visible in the scene.

const configurationUuids = ['abc', 'def']
const showDimensionsInViewer = true

api.configurator.getConfigurationDimensions = (

It can be also used to get the dimensions of a single configuration by passing only one element to the uuids array.


Change camera angle

api.scene.setCameraAngles(horizontalAngle, verticalAngle)
Sets camera angle to set value (-180-180).

Toggle camera position (menu)

Triggers Camera Positions in the action menu

Load camera position

Sets the camera to a set camera position.


Screenshot as data url

        format?: 'png' | 'jpeg';
        keepPosition?: boolean; // Keep position of camera
        horizontalAngle?: number;
        verticalAngle?: number;
        width?: number;
        height?: number;
    ): string

api.scene.requestScreenshot().then(data => console.log(data));
Lists event details to console.

Example data received:
  dataUrl: "data:image/jpeg;base64,/9j/4AAQSkZJRgABAQAAAQABAAD...",
  verticalAngle: 15,
  horizontalAngle: -35,

Take screenshot (menu)

api.scene.takePhoto({ download: boolean });
Triggers Screenshot in the action menu.


Toggle lights (menu)

Triggers Toggle Lights in the action menu.


Toggle annotations (menu)

Triggers Annotations in the action menu.

Select annotation by uuid

Loads selected annotation.

Unselect annotation

Unselect the selected annotation.

3D Text (troika-three-text)

Create and customize your 3D text using the troika-three-text package attributes.

More information on the feature can be found:

Update text node

api.scene.updateTextNode(text: string)
Set 3D text to set value.

Update text styling

All of these fields are optional.

api.scene.updateTextNodeAttributes(attributes: {
    anchorX: number;
    anchorY: number;
    clipRect: string;
    color: ColorRepresentation;
    curveRadius: number;
    depthOffset: number;
    direction: 'auto' | 'rtl' | 'ltr';
    fillOpacity: number;
    font: string;
    fontSize: number;
    glyphGeometryDetail: number;
    letterSpacing: number;
    lineHeight: 'normal' | number;
    maxWidth: number;
    outlineBlur: number;
    outlineColor: ColorRepresentation;
    outlineOffsetX: number;
    outlineOffsetY: number;
    outlineOpacity: number;
    outlineWidth: number;
    overflowWrap: 'normal' | 'word-wrap';
    sdfGlyphSize: number;
    strokeColor: ColorRepresentation;
    strokeOpacity: number;
    strokeWidth: number;
    textAlign: string;
    textIndent: number;
    whiteSpace: 'normal' | 'nowrap';
}): void

Dynamic Material API

How to use?

console.log(api.scene.getAllMaterialUuids()); // Get all materials

// Update albedoColour
api.scene.updateMaterial("material-uuid", {
  albedoColour: { red: 255, green: 0, blue: 0 },

// Change texture
api.scene.updateMaterial("material-uuid", {

// Update multiple fields
api.scene.updateMaterial("material-uuid", {
  albedoColour: { red: 255, green: 0, blue: 0 },
  metalness: 1,
  roughness: 0,
  emissiveColour: { red: 0, green: 0, blue: 200 },

Example integration:

Update material

api.scene.updateMaterial(materialUuid, {})
Updates Material properties.

Material fields

albedoColour: { red: number; green: number; blue: number; alpha: number; }
hasAlbedoTransparency: boolean;
albedoTexture: ''
metalness: number;
metalnessTexture: ''
roughness: number;
roughnessTexture: ''
normalTextureIntensity: number;
normalTexture: ''
occlusionTextureIntensity: number;
occlusionTexture: ''
emissiveColour: { red: number; green: number; blue: number; }
emissiveTextureIntensity: number;
emissiveTexture: ''

Material updated

Sent when material update is visible in the 3D Viewer

Extension fields


volumeExtension needs to be set to true

volumeExtension: boolean;
thicknessTexture: ''
attenuationColour: { red: number; green: number; blue: number; }
thicknessFactor: number;
attenuationDistance: number;

Clear coat

clearcoatExtension needs to be set to true

clearcoatExtension: boolean;
clearcoatFactor: number;
clearcoatRoughnessFactor: number;
clearcoatTexture: ''
clearcoatNormalTexture: ''
clearcoatRoughnessTexture: ''


iorExtension needs to be set to true

iorExtension: boolean;
ior: number;


sheenExtension needs to be set to true

sheenExtension: boolean;
sheenTexture: ''
sheenRoughnessTexture: ''
sheenColour: { red: number; green: number; blue: number; }
sheenRoughnessFactor: number;


transmissionExtension needs to be set to true

transmissionExtension: boolean;
transmissionFactor: number;
transmissionTexture: ''

Transform (tiling)

transformExtension needs to be set to true

transformExtension: boolean;
tiling: { x: number; y: number; }
tilingOffset: { x: number; y: number; }
tilingRotation: { x: number; y: number; }

Dynamic TRS API

How to use?

console.log(api.scene.getAllNodeUuids()) // get all node uuids

  api.scene.updateNode("node-uuid", {
    translation: { 1, 1, 1 },
    rotation: { 0, 0, 180 },
    scale: { 2, 2, 2 }

Example integration:

Get all node uuids


Update node

api.scene.updateNode("node-uuid", {
    translation: { 1, 1, 1 },
    rotation: { 0, 0, 180 },
    scale: { 2, 2, 2 }


translation: { x: number; y: number; z: number; }
rotation: { x: number; y: number; z: number; }
scale: { x: number; y: number; z: number; }

Updated on: 02/08/2023

Was this article helpful?

Share your feedback


Thank you!