@alliumcloud/configurator-service
v1.3.1
Published
Allium Configurator SDK - manages sketchfab 3D object , manages live stream, video and links and manages position,scale,rotation of all objects
Readme
@alliumcloud/configurator-service
Official TypeScript SDK for the Allium Configurator backend. Provides a fully typed, modular HTTP client for all space configuration operations — media screens, 3D objects, transforms, layers, and configurator items.
Table of Contents
- Installation
- Quick Start
- Architecture
- Configuration
- Error Handling
- Debug Logging
- API Reference
- Types Reference
- Versioning
Installation
npm install @alliumcloud/configurator-service
# or
yarn add @alliumcloud/configurator-service
# or
pnpm add @alliumcloud/configurator-serviceQuick Start
import { createConfiguratorSDK } from "@alliumcloud/configurator-service";
// Initialize once — pass your API key, that's it.
const sdk = createConfiguratorSDK({
apiKey: "your-api-key",
jwksUri: "https://your-auth-domain/.well-known/jwks.json", // JWKS is optional here
accessTokenProvider: async () => await yourAuthService.getToken(),
});
// Add a 3D model to a space
await sdk.sketchfab.addObject({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "My Model",
type: "RuntimeModel",
gltfUrl: "https://...",
materialOverrideId: "None",
scale: { x: 1, y: 1, z: 1 },
autoScale: true,
offsetUniformScale: 1,
collisionsEnabled: false,
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
offsetUpRotation: 0,
});
// Update its position
await sdk.transform.updatePosition("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
position: { x: 3, y: 0, z: 0 },
});You can also use the namespace default export:
import ConfiguratorSDK from "@alliumcloud/configurator-service";
const sdk = ConfiguratorSDK.create({
apiKey: "your-api-key",
jwksUri: "https://your-auth-domain/.well-known/jwks.json", // JWKS is optional here
accessTokenProvider: async () => await yourAuthService.getToken(),
});Architecture
The SDK is structured as a set of isolated, focused modules. Each module handles one domain of the backend API. All modules share a single configured HTTP client that is created once at initialization.
createConfiguratorSDK({ apiKey })
│
├── sdk.media → /media
├── sdk.sketchfab → /sketchfab
├── sdk.transform → /transform
├── sdk.layer → /layer
├── sdk.configuratorItems → /configurator_items
└── sdk.configuratorObjects → /configurator_objectsKey design decisions:
- The backend base URL is baked into the SDK at build time. You never pass a URL — it is not configurable by consumers.
- Your API key is passed once at initialization and is automatically injected as
x-sdk-keyon every request. - All errors are normalized into typed
AlliumErrorobjects with acodeandnameso you can catch them reliably. - Debug logging is fully opt-in and zero-cost in production.
Configuration
import {
createConfiguratorSDK,
ConfiguratorServiceSDKConfig,
} from "@alliumcloud/configurator-service";
const sdk = createConfiguratorSDK({
apiKey: "your-api-key",
jwksUri: "https://your-auth-domain/.well-known/jwks.json",
accessTokenProvider: async () => await yourAuthService.getToken(),
timeout: 60_000,
});| Option | Type | Required | Default | Description |
| --------------------- | --------------------------------- | -------- | ------- | ------------------------------------------------------------------------------- |
| apiKey | string | Yes | — | API key issued after SDK purchase. Sent as x-sdk-key header on every request. |
| jwksUri | string | No | — | JWKS endpoint URI. Sent as x-jwks-uri on every request. |
| accessTokenProvider | () => string \| Promise<string> | Yes | — | Called before every request to retrieve a Bearer token. |
| timeout | number | No | 30000 | Request timeout in milliseconds. |
Error Handling
All SDK errors are instances of AlliumError. You can use isAlliumError() to safely narrow the type in catch blocks.
import { isAlliumError } from "@alliumcloud/configurator-service";
try {
await sdk.sketchfab.addObject({ ... });
} catch (err) {
if (isAlliumError(err)) {
console.log(err.name); // e.g. 'AlliumAuthError'
console.log(err.code); // e.g. 'AUTH_ERROR'
console.log(err.message); // human-readable description
}
}Error Types
| err.name | err.code | When it is thrown |
| ----------------------- | ------------------ | ----------------------------------------------------------- |
| AlliumConfigError | INVALID_CONFIG | API key is missing or base URL not configured in the build. |
| AlliumAuthError | AUTH_ERROR | Server returns 401 or 403 — key is invalid or expired. |
| AlliumValidationError | VALIDATION_ERROR | Server returns 400 or 422 — bad input data. |
| AlliumRequestError | REQUEST_ERROR | Network failure, timeout, or any other 5xx response. |
| AlliumSDKError | SDK_ERROR | Generic fallback for uncategorized errors. |
Debug Logging
The SDK ships with a built-in debug logger that is completely silent by default. Enable it to see every outgoing request, response status, and module-level operation in your console.
In Node.js:
ALLIUM_DEBUG=true node your-script.jsIn the browser:
window.ALLIUM_DEBUG = true;All log lines are prefixed with a timestamp and category:
[14:23:01.452][SDK:HTTP] → POST /sketchfab/object
[14:23:01.891][SDK:HTTP] ← 200 /sketchfab/object
[14:23:01.892][SDK:Sketchfab] addObject { orgId: '...', spaceItemId: '...' }API Reference
Media
sdk.media.addVideo(data)
Add a Vimeo video screen to a space.
await sdk.media.addVideo({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "My Video",
type: "SpatialMedia",
mediaType: "video",
url: "https://vimeo.com/...",
attenuation: 1000,
volume: 100,
loop: true,
audioOnly: false,
showPreview: false,
position: { x: 0, y: 1, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
offsetUpRotation: 0,
});Returns: Promise<void>
sdk.media.updateVideo(spaceItemId, data)
Update properties of an existing video screen.
await sdk.media.updateVideo("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
url: "https://vimeo.com/new-video",
volume: 80,
loop: false,
});| Field | Type | Required | Description |
| ------------- | --------- | -------- | ----------------------------- |
| orgId | string | Yes | Organization ID. |
| spaceId | string | Yes | Space ID. |
| spaceItemId | string | Yes | Space item ID. |
| url | string | No | New Vimeo URL. |
| volume | number | No | Volume level (0–100). |
| attenuation | number | No | Audio attenuation distance. |
| loop | boolean | No | Whether to loop the video. |
| audioOnly | boolean | No | Play audio only, no visuals. |
| showPreview | boolean | No | Show video preview thumbnail. |
Returns: Promise<void>
sdk.media.addLink(data)
Add a website link screen to a space.
await sdk.media.addLink({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "My Link",
type: "SpatialMedia",
mediaType: "link",
url: "https://example.com",
attenuation: 1000,
isPortrait: false,
openInNewTab: true,
position: { x: 0, y: 1, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
offsetUpRotation: 0,
});Returns: Promise<void>
sdk.media.updateLink(spaceItemId, data)
Update properties of an existing link screen.
await sdk.media.updateLink("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
url: "https://new-url.com",
isPortrait: true,
});| Field | Type | Required | Description |
| -------------- | --------- | -------- | ------------------------------- |
| orgId | string | Yes | Organization ID. |
| spaceId | string | Yes | Space ID. |
| spaceItemId | string | Yes | Space item ID. |
| url | string | No | New website URL. |
| name | string | No | Display name. |
| openInNewTab | boolean | No | Open link in a new tab. |
| isPortrait | boolean | No | Render screen in portrait mode. |
Returns: Promise<void>
sdk.media.addStream(data)
Add a live stream screen to a space.
await sdk.media.addStream({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "My Stream",
type: "RuntimeStream",
spaceStreamId: "stream-id",
scale: { x: 1, y: 1, z: 1 },
offsetUniformScale: 1,
attenuation: 1000,
volume: 100,
audioOnly: false,
position: { x: 0, y: 1, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
offsetUpRotation: 0,
});Returns: Promise<void>
sdk.media.updateStream(spaceItemId, data)
Update properties of an existing stream screen.
await sdk.media.updateStream("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
volume: 50,
aspectRatio: "16:9",
attenuation: 2000,
});| Field | Type | Required | Description |
| ------------- | ----------------- | -------- | --------------------------------------- |
| orgId | string | Yes | Organization ID. |
| spaceId | string | Yes | Space ID. |
| spaceItemId | string | Yes | Space item ID. |
| audioOnly | boolean | No | Play audio only. |
| curvature | number | No | Screen curvature (−100 to 100). |
| brightness | number | No | Screen brightness (0.0 to 5.0). |
| contrast | number | No | Screen contrast (0.5 to 1.5). |
| saturation | number | No | Screen saturation (0.0 to 3.0). |
| gamma | number | No | Screen gamma (0.1 to 3.0). |
| aspectRatio | "4:3" \| "16:9" | No | Screen aspect ratio. |
| attenuation | number | No | Audio attenuation distance (200–10000). |
| volume | number | No | Volume level (0–100). |
Returns: Promise<void>
Sketchfab
sdk.sketchfab.addObject(data)
Add a 3D model to a space. Supports Sketchfab browse, file upload, and recent model reuse — all produce the same payload shape.
await sdk.sketchfab.addObject({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "My Model",
type: "RuntimeModel",
gltfUrl: "https://...",
materialOverrideId: "None",
scale: { x: 1, y: 1, z: 1 },
autoScale: true,
offsetUniformScale: 1,
collisionsEnabled: false,
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
offsetUpRotation: 0,
metadata: {
uid: "sketchfab-uid",
author: { username: "artist", profileUrl: "https://sketchfab.com/artist" },
},
});Returns: Promise<void>
sdk.sketchfab.updateObject(spaceItemId, data)
Update collision and animation properties of an existing 3D model.
await sdk.sketchfab.updateObject("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
collisionsEnabled: true,
currentAnimation: "Walk",
});| Field | Type | Required | Description |
| ------------------- | --------- | -------- | ------------------------------ |
| orgId | string | Yes | Organization ID. |
| spaceId | string | Yes | Space ID. |
| spaceItemId | string | Yes | Space item ID. |
| collisionsEnabled | boolean | No | Enable or disable collisions. |
| currentAnimation | string | No | Name of the animation to play. |
Returns: Promise<void>
Transform
sdk.transform.updatePosition(spaceItemId, data)
Update the world position of a space item.
await sdk.transform.updatePosition("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
position: { x: 3, y: 0, z: 0 },
});Returns: Promise<void>
sdk.transform.updateRotation(spaceItemId, data)
Update the rotation of a space item.
await sdk.transform.updateRotation("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
rotation: { x: 0, y: 90, z: 0 },
offsetUpRotation: 45,
});| Field | Type | Required | Description |
| ------------------ | --------- | -------- | ------------------------------------------ |
| orgId | string | Yes | Organization ID. |
| spaceId | string | Yes | Space ID. |
| spaceItemId | string | Yes | Space item ID. |
| rotation | Vector3 | Yes | Rotation in degrees per axis. |
| offsetUpRotation | number | No | Additional up-axis rotation (−180 to 180). |
Returns: Promise<void>
sdk.transform.updateScale(spaceItemId, data)
Update the scale of a space item.
await sdk.transform.updateScale("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
scale: { x: 2, y: 2, z: 2 },
offsetUniformScale: 2,
});| Field | Type | Required | Description |
| -------------------- | --------- | -------- | ------------------------------------ |
| orgId | string | Yes | Organization ID. |
| spaceId | string | Yes | Space ID. |
| spaceItemId | string | Yes | Space item ID. |
| scale | Vector3 | No | Per-axis scale values. |
| offsetUniformScale | number | Yes | Uniform scale multiplier (min 0.01). |
Returns: Promise<void>
sdk.transform.snapToGround(spaceItemId, data)
Snap a space item to the ground. The UE bridge calculates the correct Z position.
await sdk.transform.snapToGround("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
});Returns: Promise<void>
Layer
sdk.layer.lockItem(spaceItemId, data)
Lock or unlock a layer item.
// Lock
await sdk.layer.lockItem("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
isLocked: true,
});
// Unlock
await sdk.layer.lockItem("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
isLocked: false,
});Returns: Promise<void>
sdk.layer.renameItem(spaceItemId, data)
Rename a layer item.
await sdk.layer.renameItem("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "New Name",
});Returns: Promise<void>
sdk.layer.deleteItem(spaceItemId, data)
Delete a single layer item from a space.
await sdk.layer.deleteItem("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
});Returns: Promise<void>
sdk.layer.deleteAll(data)
Delete all layer items in a space. Locked items are skipped by the organization service.
await sdk.layer.deleteAll({
orgId: "org-id",
spaceId: "space-id",
});Returns: Promise<void>
Configurator Items
sdk.configuratorItems.create(data)
Create a configurator item. Typically synced from Unreal Engine on session start via the WebRTC bridge.
await sdk.configuratorItems.create({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
itemTemplateId: "template-id",
name: "Wall Color",
denormalizeOnUpdate: true,
currentState: "white",
schema: {
displayName: "Wall Color",
type: "enum",
default: "white",
values: ["white", "grey", "black"],
},
});Returns: Promise<void>
sdk.configuratorItems.updateState(spaceItemId, data)
Update the current state of a level-wide configurator property.
await sdk.configuratorItems.updateState("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
currentState: "grey",
});Returns: Promise<void>
Configurator Objects
sdk.configuratorObjects.create(data)
Place a UE actor in a space. Called when a user selects a card in the UE Object Importer grid.
await sdk.configuratorObjects.create({
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
name: "My Chair",
type: "ConfiguratorObject",
ueId: "ue-actor-id",
versionId: "version-id",
scale: { x: 1, y: 1, z: 1 },
offsetUniformScale: 1,
position: { x: 0, y: 0, z: 0 },
rotation: { x: 0, y: 0, z: 0 },
offsetUpRotation: 0,
configuration: {
color: {
displayName: "Color",
type: "enum",
currentState: "red",
default: "red",
values: ["red", "blue", "green"],
displayType: "dropdown",
},
},
});Returns: Promise<void>
sdk.configuratorObjects.updateConfiguration(spaceItemId, data)
Update the full configuration map of a placed UE actor. Updates the entire map with new currentState per key.
await sdk.configuratorObjects.updateConfiguration("item-id", {
orgId: "org-id",
spaceId: "space-id",
spaceItemId: "item-id",
configuration: {
color: {
displayName: "Color",
type: "enum",
currentState: "blue",
default: "red",
values: ["red", "blue", "green"],
displayType: "dropdown",
},
},
});Returns: Promise<void>
Types Reference
All types are exported directly from the package root:
import type { ... } from "@alliumcloud/configurator-service";Config
type ConfiguratorServiceSDKConfig = {
apiKey: string;
jwksUri?: string;
accessTokenProvider: () => string | Promise<string>;
timeout?: number;
};Common
type SpaceItemType =
| "RuntimeModel"
| "SpatialMedia"
| "LibraryModel"
| "RuntimeStream"
| "BridgeToolkitSettings"
| "Configurator"
| "ConfiguratorObject";
type ConfiguratorType =
| "string"
| "number"
| "boolean"
| "enum"
| "trigger"
| "image"
| "String"
| "Number"
| "Bool"
| "Enum"
| "Trigger"
| "Image";
type Vector3 = {
x: number;
y: number;
z: number;
};
type SpaceContext = {
orgId: string;
spaceId: string;
type: SpaceItemType;
name: string;
position: Vector3;
rotation: Vector3;
offsetUpRotation: number;
thumb?: string;
isLocked?: boolean;
user?: string;
};Media Types
type SpatialMediaTypes = "video" | "link";
type CreateVideoInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
name: string;
type: "SpatialMedia";
mediaType: "video";
url: string;
attenuation: number;
volume: number;
loop: boolean;
audioOnly: boolean;
showPreview: boolean;
autoplay?: boolean;
position: Vector3;
rotation: Vector3;
offsetUpRotation: number;
thumb?: string;
isLocked?: boolean;
user?: string;
};
type UpdateVideoInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
url?: string;
volume?: number;
attenuation?: number;
loop?: boolean;
audioOnly?: boolean;
showPreview?: boolean;
};
type CreateLinkInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
name: string;
type: "SpatialMedia";
mediaType: "link";
url: string;
attenuation: number;
isPortrait: boolean;
openInNewTab?: boolean;
displayName?: string;
position: Vector3;
rotation: Vector3;
offsetUpRotation: number;
thumb?: string;
isLocked?: boolean;
user?: string;
};
type UpdateLinkInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
url?: string;
name?: string;
openInNewTab?: boolean;
isPortrait?: boolean;
};
type CreateStreamInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
name: string;
type: "RuntimeStream";
spaceStreamId: string;
scale?: Vector3;
autoScale?: boolean;
offsetUniformScale?: number;
attenuation?: number;
volume?: number;
audioOnly?: boolean;
position: Vector3;
rotation: Vector3;
offsetUpRotation: number;
thumb?: string;
isLocked?: boolean;
user?: string;
};
type UpdateStreamInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
audioOnly?: boolean;
curvature?: number;
aspectRatio?: "4:3" | "16:9";
attenuation?: number;
volume?: number;
};Sketchfab Types
type ModelAuthor = {
username: string;
profileUrl: string;
};
type ModelGlbInfo = {
faceCount?: number;
textureCount?: number;
size?: number;
vertexCount?: number;
textureMaxResolution?: number;
};
type ModelMetadata = {
uid?: string;
viewerUrl?: string;
author?: ModelAuthor;
license?: string;
glb?: ModelGlbInfo;
};
type CreateSketchfabObjectInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
name: string;
type: "RuntimeModel";
gltfUrl?: string;
materialOverrideId: string;
scale: Vector3;
autoScale: boolean;
offsetUniformScale: number;
collisionsEnabled: boolean;
currentAnimation?: string;
availableAnimations?: string[];
metadata?: ModelMetadata;
thumb?: string;
sketchfabTempUrl?: string;
position: Vector3;
rotation: Vector3;
offsetUpRotation: number;
isLocked?: boolean;
user?: string;
};
type UpdateSketchfabObjectInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
collisionsEnabled?: boolean;
currentAnimation?: string;
};Transform Types
type TransformItemContext = {
orgId: string;
spaceId: string;
spaceItemId: string;
};
type UpdatePositionInput = TransformItemContext & {
position: Vector3;
};
type UpdateRotationInput = TransformItemContext & {
rotation: Vector3;
offsetUpRotation?: number;
};
type UpdateScaleInput = TransformItemContext & {
scale?: Vector3;
offsetUniformScale: number;
};
type SnapToGroundInput = TransformItemContext;Layer Types
type LockLayerItemInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
isLocked: boolean;
};
type RenameLayerItemInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
name: string;
};
type DeleteLayerItemInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
};
type DeleteAllLayerItemsInput = {
orgId: string;
spaceId: string;
};Configurator Item Types
type ConfiguratorItemSchema = {
displayName: string;
type: ConfiguratorType;
default: string | number | boolean;
values?: (string | number)[];
max?: number;
min?: number;
step?: number;
isPersisted?: boolean;
isNetworked?: boolean;
};
type CreateConfiguratorItemInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
itemTemplateId: string;
name: string;
levelFilePath?: string;
denormalizeOnUpdate: boolean;
currentState?: string | number | boolean;
schema: ConfiguratorItemSchema;
};
type UpdateConfiguratorItemStateInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
currentState: string | number | boolean;
};Configurator Object Types
type ObjectConfigurationValue = {
displayName: string;
type: ConfiguratorType;
currentState: string | number | boolean;
default: string | number | boolean;
max?: number;
min?: number;
step?: number;
values: (string | number)[];
displayType?: "image" | "dropdown";
valuesImages?: { displayName: string; thumb?: string }[];
};
type EnumObjectConfigurationValue = {
displayName: string;
type: "enum";
currentState: string | number;
default: string | number;
values: (string | number)[];
displayType: "image" | "dropdown";
max?: number;
min?: number;
step?: number;
valuesImages?: { displayName: string; thumb?: string }[];
};
type ConfigurationMap = {
[key: string]: ObjectConfigurationValue | EnumObjectConfigurationValue;
};
type CreateConfiguratorObjectInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
name: string;
type: "ConfiguratorObject";
ueId: string;
versionId: string;
scale: Vector3;
offsetUniformScale: number;
configuration: ConfigurationMap;
position: Vector3;
rotation: Vector3;
offsetUpRotation: number;
thumb?: string;
isLocked?: boolean;
user?: string;
};
type UpdateConfiguratorObjectConfigInput = {
orgId: string;
spaceId: string;
spaceItemId: string;
configuration: ConfigurationMap;
};Error Types
interface AlliumError extends Error {
readonly code: string; // Machine-readable error code
readonly name: string; // Human-readable error name
readonly message: string; // Description of what went wrong
}
// Type guard — use in catch blocks to narrow the error type
function isAlliumError(err: unknown): err is AlliumError;Versioning
This SDK follows semantic versioning:
| Bump | When |
| ----------------- | -------------------------------------------------------- |
| patch — x.x.1 | Bug fixes, no API changes. |
| minor — x.1.0 | New methods or fields added, fully backwards compatible. |
| major — 2.0.0 | Breaking changes to existing method signatures or types. |
License
Private — Allium Internal Use Only
