API
- 🔧 GitHub Repository: github.com/orbitalvision/ov25-ui - Forks welcome!
1. Overview
The Orbital Vision 3D Configurator is a self-contained application embedded inside an <iframe>. The parent application can communicate with it to:
- Load or switch between products or ranges.
- Select product options (e.g., fabrics, legs, sizes).
- View or hide product dimensions.
- Enter AR or VR modes (where supported).
- Listen for updates (e.g., current price, SKU, etc.).
Communication is done via the standard Window.postMessage API.
2. iFrame URL Requirements
When embedding the configurator, you must include:
- Your API key, which authenticates the request.
You can create a new API key in your dashboard at app.orbital.vision/auth/api-keys. Please select the Product Configurator Access type from the dropdown list.
- Either a product ID or a range ID.
You can find your desired product ID or range ID by going to app.orbital.vision/products. On the lefthand side of the table there is an ID field for both ranges and products.
This requirement gives two possible URL structures:
- Product-Based
- Structure: https://configurator.orbital.vision***/[API_KEY]/[PRODUCT_ID]***
- Example:
https://configurator.orbital.vision/abc123/45
- Range-Based
- Structure: https://configurator.orbital.vision***/[API_KEY]/***range***/[RANGE_ID]***
- Example:
https://configurator.orbital.vision/abc123/range/99
- Authorised Domain
- The site where the iframe is hosted must be one of your authorised domains listed on your dashboard at app.orbital.vision/authorized-domains
The [API_KEY] ensures that only authorised integrations can load the 3D environment. Without it, the server hosting the configurator will reject the request.
Required <iframe> Attributes
To enable a full range of features-particularly WebXR (AR/VR) support-the following allow attributes are required:
accelerometer: Allows the 3D configurator to access device orientation data, used for augmented reality interactions on mobile.autoplay: Permits automatic playback of any embedded 3D or media assets without explicit user interaction.clipboard-write: Allows copying data to the user's clipboard. This may be used for future feature support (for example, quickly sharing config data).encrypted-media: Enables playback of protected or DRM-encrypted content if the configurator requires secure media streams.gyroscope: Grants access to motion sensors needed for advanced AR or VR features on mobile devices.picture-in-picture: Allows the configurator to enter picture-in-picture mode in future updates.xr-spatial-tracking: Essential for AR or VR sessions under WebXR, enabling correct spatial tracking of the virtual object in a real-world environment.fullscreen: Permits the configurator to be viewed in full screen, improving the immersive 3D or AR/VR experience.
3. Initial Handshake: Messages from the Configurator
When the configurator finishes loading, it will send messages to the parent window detailing its initial state. These messages will then resend any time the data in the previous messages becomes stale.
ALL_PRODUCTS
Description:
A complete list of products the configurator can display at load time, this will have a single product only if you did not use the range path.
Example:
priceandpricingare always in the lowest form of that currency, for example in pence (e.g.,150000= £1,500.00).
RANGE
Description:
Information about the range currently in use (if you're loading a range-based URL).
Example:
idmatches the[RANGE_ID]passed in the URL.
CURRENT_PRODUCT_ID
Description:
Tells you which specific product is currently loaded by the configurator.
Example:
payloadis a simple number in this case (the product ID).
CONFIGURATOR_STATE
Description:
The complete structure of the configurator, detailing available options, groups, selections, and the user's current selections.
Quite often the group name will be 'Default Group' or 'Default' if there is only one group, so when designing your UI we recommend hiding groups and just showing the selections directly nested within their option when there exists only a single group.
Example:
- Each selection comes with a thumbnail, and mini thumbnails. The mini thumnails are sized 50px, 150px and 250px (small, medium large)
- They are all webp which as you can see from https://caniuse.com/webp is supported in nearly all browsers. In 2025 it is completely safe to use and we recommend that you use these performant mini thumbnails. If you do not want to use them, there is also the original thumbnail jpg for you to use with an image service/cdn.
- Each option can contain one or more groups. Each group can contain one or more selections.
- selectedSelections tells you exactly which
selectionIdthe user has chosen for each option/group.
CURRENT_PRICE
Description:
The calculated price based on the user's current selections.
Example:
formattedPriceis a user-facing string (localized).totalPriceis an integer in the lowest form of that currency (103600 = £1,036.00).subtotalis the price before any discounts are applied (129500 = £1,295.00).formattedSubtotalis the formatted string representation of the subtotal.discountcontains the discount information withamount(in lowest currency form),formattedAmount(localized string), andpercentage(discount percentage).priceBreakdownis a breakdown of the total price, including the price of the range, product, and any selections such as fabric or legs. This will sum to subtotal.- Each
priceBreakdownrow also containssubtotal,formattedSubtotal,discountedAmount,formattedDiscountAmountanddiscountPercentagefor that line.
Multi-product modular (snap2) CURRENT_PRICE
For multi-product modular configurators, the iframe replaces priceBreakdown with productBreakdowns - one entry per product type in the scene, each with its own quantity, selections and per-line discount fields.
productIdmatches the corresponding key in the multi-productCURRENT_SKUpayload, andmodelIdmatches the underlying 3D model.priceis per-line total (already multiplied byquantity);subtotalis the per-unit price before quantity.selectionslists the per-product cost contribution of each currently selected option (e.g. fabric, legs).- If you are integrating via the
ov25-uipackage, bothpriceBreakdownandproductBreakdownsare normalized into a unifiedlines[]array withmode: 'single' | 'multi'. See the UI Package Integration guide.
CURRENT_SKU
Description:
The SKU representing the current product configuration. Helpful for backend or e-commerce tracking.
The shape differs between standard single-product configurators and multi-product modular (snap2) configurators.
Single-product example:
Multi-product modular (snap2) example:
The payload is an object keyed by productId. Each entry is a billable line in the scene (one entry per product type, with its own quantity).
skuStringis a/separated combination of the product SKU and each selection SKU.skuMapshows how each option name maps to the underlying SKU.- For multi-product modular configurators, iterate
Object.entries(payload)- each value has its ownskuString,skuMapandquantity. - If you are integrating via the
ov25-uipackage, both shapes are normalized into a singleOnChangePayloadwithmode: 'single' | 'multi'andlines[]. See the UI Package Integration guide.
SELECTED_SELECTIONS
Description:
The full set of currently selected { optionId, groupId, selectionId } triples. Sent any time the selection set changes (in addition to CONFIGURATOR_STATE). Useful if you want a lightweight signal of selection changes without re-parsing the entire configurator state.
Example:
AR_PREVIEW_LINK
Description:
A direct link to an AR experience, used when the current device is not appropriate.
Example:
- It is recommended that you display this link with a QR code to scan from a mobile device.
- On iOS devices, this will open AR Quick Look. Unfortunately apple refuses to support other methods such as webXR which are otherwise universally supported. Additionally, USDZ does not have full support for lighting/custom shaders and there is also a hard limit on textures that we can use in the material. This leads to a huge loss of quality when using AR on any IOS device, such as an iPhone. We are actively monitoring changes from apple and if it becomes possible in the future, we will address this.
AVAILABLE_CAMERAS
Description:
The list of camera presets the configurator exposes for the current product (if any). Sent whenever the camera list changes.
Example:
Send SELECT_CAMERA (see section 7) to switch to a given camera by id.
AVAILABLE_LIGHTS
Description:
The list of light groups (lighting presets) available for the current scene. Sent whenever the light group list changes.
Example:
Send SELECT_LIGHT (see section 7) to switch to a given light group by id.
AVAILABLE_FABRICS
Description:
For fabric-account integrations, the list of fabrics that can be applied as a material override on the current product. Only sent when fabric overrides are available.
Example (truncated):
Send SET_FABRIC_OVERRIDE (see section 7) to apply a fabric to a specific material.
COMPATIBLE_MODULES (multi-product modular only)
Description:
For multi-product modular (snap2) configurators, the list of modules that can be added or substituted at the user's current selection point. Sent on initial load and any time the selected attachment point or selected object changes.
Example:
- When
isInitialLoad === true, the array contains every available module for the initial pick (no scene yet). - After the first module is placed, the array will only contain modules compatible with the currently selected attachment point or object, or be empty when nothing is selected.
Send SELECT_MODULE (see section 7) to add or replace a module.
SELECT_MODULE_RECEIVED (multi-product modular only)
Acknowledgement of a SELECT_MODULE command. Payload: { "success": boolean, "modelPath": string, "modelId": string }.
SCREENSHOT_URL
Description:
Response to CAPTURE_SCREENSHOT (see section 7). Contains the uploaded URL of the captured PNG screenshot of the configurator viewport.
If the capture fails, an ERROR message is sent instead (see below).
CAMERA_RECENTERED
Description:
Acknowledgement of a RECENTER_CAMERA command. Payload: { "success": true }.
SNAP2_SAVE_RESPONSE (multi-product modular only)
Description:
Response to REQUEST_SNAP2_SAVE. Returns the saved configuration UUID that can later be passed back as configurationUuid to restore the scene.
On failure: { "success": false, "error": "<message>" }.
CURRENT_BED_SIZE (bed configurator only)
Description:
For bed configurators, the currently selected bed size. Sent whenever the bed size changes.
ANIMATION_STATE
Description:
Notifies the parent of the current animation state for the loaded model. Sent on every state change.
Possible string values: "unavailable", "stop", "loop", "open", "close".
SHOW_OPTION / HIDE_OPTION / SHOW_GROUP / HIDE_GROUP / SHOW_SELECTION / HIDE_SELECTION
Description:
Diff events emitted whenever the visible UI structure changes (for example after a rule hides a group, or when fabric overrides bring a previously-hidden option back). Useful if your parent UI is mirroring the configurator's option/group/selection tree and you want to track visibility without re-diffing CONFIGURATOR_STATE yourself.
TRANSITION_SNAPSHOT / TRANSITION_SNAPSHOT_ERROR
Description:
Response to a REQUEST_TRANSITION_SNAPSHOT command (see section 7). Used to capture a low-latency ImageBitmap of the canvas for transition animations between products.
TRANSITION_SNAPSHOT is not a JSON payload - the ImageBitmap is sent as a transferable on the message itself:
On failure: { type: "TRANSITION_SNAPSHOT_ERROR", requestId, payload: '{"message":"..."}' }.
ERROR
Description:
Generic error response. Sent when an inbound command (e.g. CAPTURE_SCREENSHOT, SELECT_CAMERA, SELECT_LIGHT, SELECT_MODULE) fails or receives an invalid payload.
IS_LOADING
Description:
Indicates whether the configurator is currently loading a new product or model. Useful for showing a loading overlay in the parent UI.
How to Use These Messages
-
All messages are posted to the parent window. You can intercept them with:
-
Parse
payloadwithJSON.parse(...)if the configurator sends it as a string. -
Update your UI or application state with product data, pricing, SKU, or AR links as needed.
4. Listening for Messages (Parent Application)
In your parent application, add an event listener for message:
5. Sending Messages to the Configurator
You can control the configurator by sending messages from the parent app to the iframe's contentWindow. For example:
Below are the most common commands:
-
SELECT_PRODUCT
Instructs the configurator to switch to another product:
-
SELECT_SELECTION
Applies a user's choice (e.g., new fabric or color) for a specific option. The iframe accepts two payload shapes on the same message type:
A. IDs (stable, recommended when you already have UUIDs from
CONFIGURATOR_STATEorSELECTED_SELECTIONS):If the payload object includes a
selectionIdproperty, it is treated as this legacy shape.B. Single display-name pair (fuzzy-matched against the live menu):
Send exactly one string key and one string value: the option display name as the key, and the selection display name (or a close variant) as the value. Useful when your storefront encodes choices as human-readable or slug-like strings instead of configurator UUIDs.
The iframe resolves this to
{ optionId, groupId, selectionId }internally, then applies the selection the same way as shape A. If the payload cannot be parsed, has more than one key–value pair, or no confident match is found, the iframe posts anERRORmessage (see section 7. Parent → Configurator Message Types (Detailed) below).How name-based matching works
Matching runs twice: first to pick a configurator option by the object key, then to pick a selection under that option by the object value. For each name string the algorithm:
- Normalize — lowercase; replace common separators (
_,-,/, punctuation) with spaces; strip non-alphanumeric characters; collapse whitespace. This turns values likeFOOT_COLOUR__MEDIUM_OAKinto comparable tokens (foot,colour,medium,oak). - Exact match — if the normalized string equals a candidate's normalized
name, that candidate wins immediately. - Token-set recall — otherwise, score each candidate by how many of its distinct tokens appear in the query (intersection ÷ number of distinct candidate tokens). This favours selections whose words are all present in the query even when the query has extra words (e.g. query tokens include
footandcolour, candidate isMedium Oak→ high score). If the best score is at least 0.5, that candidate is accepted. Ties are broken by Levenshtein distance on the sorted space-joined token strings, then by Levenshtein on the full normalized strings. - Whole-string Levenshtein fallback — if the token score is below 0.5, the best candidate is still accepted when its normalized full-string edit distance to the query is within a length-scaled cap:
min(24, max(3, ceil(queryCharacterLength × 0.22))). This catches near-misses such as singular vs plural (LegvsLegs).
Caveats: If two selections under the same option share the same display name (or fuzzy-tie), the first matching row in menu order may win. Prefer shape A when you need deterministic behaviour.
- Normalize — lowercase; replace common separators (
-
VIEW_DIMENSIONS
Shows or hides dimension lines on the 3D model. Optionally pass
stylesto override the iframe overlay CSS that the dimension annotations live inside (useful when the host page styles differ from the iframe's defaults): -
VIEW_MINI_DIMENSIONS (multi-product modular only)
Toggles the smaller per-module dimension overlays in snap2 scenes. Same payload shape as
VIEW_DIMENSIONS. -
ENTER_AR
Attempts to start an augmented reality session or, if necessary, returns an
AR_PREVIEW_LINKthat you can display. You may passuserAgentType("ios" | "android" | undefined) to force which AR pipeline to attempt: -
ENTER_VR
(If supported) instructs the configurator to begin a VR session:
-
TOGGLE_ANIMATION
Cycles through animation states for the loaded model (
stop↔loop,open↔close). The new state is broadcast back viaANIMATION_STATE. -
CAPTURE_SCREENSHOT
Captures a PNG of the current viewport, uploads it, and replies with a
SCREENSHOT_URLmessage (or anERRORon failure). -
SELECT_CAMERA
Switches to one of the cameras advertised in
AVAILABLE_CAMERAS. Payload is the cameraidas a JSON value. -
RECENTER_CAMERA
Recenters the active camera on the current model. Replies with
CAMERA_RECENTERED. -
SELECT_LIGHT
Switches to one of the light groups advertised in
AVAILABLE_LIGHTS. Payload is the light groupidas a JSON value. -
SET_FABRIC_OVERRIDE (fabric accounts only)
Applies a fabric texture (from
AVAILABLE_FABRICS) to a specific named material on the current product. -
SELECT_MODULE (multi-product modular only)
Adds a new module to the scene (when nothing is placed yet) or replaces the currently selected module. Use the
modelPathandmodelIdfrom aCOMPATIBLE_MODULESentry. -
CLOSE_MODULE_SELECT_MENU (multi-product modular only)
Clears the currently selected attachment point and selected object, closing any module-picker UI driven from
COMPATIBLE_MODULES. -
REQUEST_SNAP2_SAVE (multi-product modular only)
Persists the current snap2 scene server-side and replies with a
SNAP2_SAVE_RESPONSEcontaining theuuid. Pass thatuuidback asconfigurationUuidon a future load to restore the scene. -
TOGGLE_HIDE_ALL (multi-product modular only)
Toggles a "hide everything" mode that visually hides all placed modules in a snap2 scene. Useful for clean screenshots or comparing layouts.
-
REQUEST_TRANSITION_SNAPSHOT
Asks the configurator to capture a low-latency
ImageBitmapof the canvas for use in a transition animation (e.g. when crossfading between products). Replies with aTRANSITION_SNAPSHOTmessage (orTRANSITION_SNAPSHOT_ERROR) carrying the samerequestId.
6. Configurator → Parent Message Types (Detailed)
Below is a reference table for all inbound messages the configurator sends and their payload content:
| Type | Meaning | Payload (JSON) |
|---|---|---|
ALL_PRODUCTS | Full list of available products. | Array of product objects, each with dimensionX, dimensionY, dimensionZ, id, manufacturerId, name, price, pricing, productId, retailerAccess, retailerId, sku and other data. |
RANGE | Data about the current range or collection. | An object with id, name, sku and possibly other range-specific fields. |
CURRENT_PRODUCT_ID | Indicates which product is actively displayed. | A single number (e.g., 45). |
CONFIGURATOR_STATE | The complete nested structure of options, groups, selections, etc. | An object that includes retailerId, screenshotThumbnail, configuratorSettings (object), options (array), selectedSelections (array), and (in snap2 scenes) snap2Objects and fabricReplaceableOptionIds / optionIdToMaterialName. |
SELECTED_SELECTIONS | Lightweight diff of currently selected { optionId, groupId, selectionId } triples. | Array of selection triples. |
CURRENT_PRICE | The order's total price and breakdown. | Object with formattedPrice, totalPrice, subtotal, formattedSubtotal, discount, and either priceBreakdown (single product) or productBreakdowns (multi-product modular). |
CURRENT_SKU | The SKU representing the user's current configuration. | Single product: object with skuString and skuMap. Multi-product modular: object keyed by productId, each value { skuString, skuMap, quantity }. |
AR_PREVIEW_LINK | A direct link to an AR preview for compatible devices. | A string containing the URL. |
SELECT_PRODUCT_RECEIVED | Confirms a SELECT_PRODUCT command was received and processed. | Typically the same ID you sent (useful for clearing loading states). |
ANIMATION_STATE | Notifies the parent of the current animation state. | One of "unavailable", "stop", "loop", "open", "close". |
AVAILABLE_CAMERAS | The available named camera presets. | Array of { id, displayName }. |
CAMERA_RECENTERED | Acknowledgement of RECENTER_CAMERA. | { success: true }. |
AVAILABLE_LIGHTS | The available named light groups. | Array of { id, displayName }. |
AVAILABLE_FABRICS | Fabrics available as material overrides (fabric accounts). | Array of fabric objects (id, name, sku, thumbnail, etc). |
COMPATIBLE_MODULES | (snap2) Modules that can be added at the current selection point. | { modules: ProductOrientation[], isInitialLoad: boolean }. |
SELECT_MODULE_RECEIVED | (snap2) Acknowledgement of SELECT_MODULE. | { success: boolean, modelPath: string, modelId: number }. |
SCREENSHOT_URL | Response to CAPTURE_SCREENSHOT. | { url: string, cdnUrl?: string }. |
SNAP2_SAVE_RESPONSE | (snap2) Response to REQUEST_SNAP2_SAVE. | { success: boolean, uuid?: string, error?: string }. |
CURRENT_BED_SIZE | (bed configurator) Current selected bed size. | { size: string | null }. |
SHOW_OPTION / HIDE_OPTION | UI visibility diff for an option. | { optionId: string }. |
SHOW_GROUP / HIDE_GROUP | UI visibility diff for a group. | { optionId, groupId }. |
SHOW_SELECTION / HIDE_SELECTION | UI visibility diff for a selection. | { optionId, groupId, selectionId }. |
TRANSITION_SNAPSHOT | Response to REQUEST_TRANSITION_SNAPSHOT. | Not JSON. Carries { requestId, bitmap: ImageBitmap } as a transferable. |
TRANSITION_SNAPSHOT_ERROR | Failure response to REQUEST_TRANSITION_SNAPSHOT. | { requestId, payload: '{"message":"..."}' }. |
IS_LOADING | Indicates the configurator is loading. | A boolean. |
ERROR | Generic error response to a failed inbound command. | { message: string } and optional context fields (e.g. name-based SELECT_SELECTION failures may include optionName and selectionName). |
7. Parent → Configurator Message Types (Detailed)
Below is a reference table for outbound messages you can send to the configurator:
| Type | Description | Expected Payload |
|---|---|---|
SELECT_PRODUCT | Loads a specific product by its ID. | A single integer representing the product ID. |
SELECT_SELECTION | Updates the user's choice for a specific option. | Either { optionId, groupId, selectionId } (when selectionId is present), or a single { "<OptionDisplayName>": "<SelectionDisplayNameOrSlug>" } pair for fuzzy resolution (see §5 item 2). |
VIEW_DIMENSIONS | Shows or hides product dimension lines. | { dimensions: boolean, styles?: object }. |
VIEW_MINI_DIMENSIONS | (snap2) Toggles per-module dimension overlays. | { dimensions: boolean, styles?: object }. |
ENTER_AR | Initiates augmented reality mode, if supported. | {} or { userAgentType: "ios" | "android" }. |
ENTER_VR | Tries to start a virtual reality session, if supported. | {}. |
TOGGLE_ANIMATION | Cycles through animation states (stop ↔ loop, open ↔ close). | {}. Affects all animation mixers in the scene. |
CAPTURE_SCREENSHOT | Captures and uploads a PNG of the current viewport. | {}. Replies with SCREENSHOT_URL or ERROR. |
SELECT_CAMERA | Switches to a camera from AVAILABLE_CAMERAS. | A string camera id (JSON). |
RECENTER_CAMERA | Recenters the active camera on the model. | {}. Replies with CAMERA_RECENTERED. |
SELECT_LIGHT | Switches to a light group from AVAILABLE_LIGHTS. | A string light group id (JSON). |
SET_FABRIC_OVERRIDE | (fabric accounts) Apply a fabric to a named material. | { materialName: string, textureId: number }. |
SELECT_MODULE | (snap2) Add or replace a module at the current selection point. | { modelPath: string, modelId: number }. |
CLOSE_MODULE_SELECT_MENU | (snap2) Clear selection and close the module picker. | {}. |
REQUEST_SNAP2_SAVE | (snap2) Persist the current scene and reply with its UUID. | {}. Replies with SNAP2_SAVE_RESPONSE. |
TOGGLE_HIDE_ALL | (snap2) Toggle a "hide everything" rendering mode. | {}. |
REQUEST_TRANSITION_SNAPSHOT | Capture an ImageBitmap of the canvas for transition animations. | { requestId: string }. Replies with TRANSITION_SNAPSHOT or TRANSITION_SNAPSHOT_ERROR. |
8. Typical Integration Flow
- Embed the iFrame
- Provide the correct URL (with your API key + product or range).
- Include the required
allowattributes for AR/VR, fullscreen, etc.
- Listen for the Handshake
- As soon as the iframe loads, it sends
ALL_PRODUCTS,CURRENT_PRODUCT_ID,CONFIGURATOR_STATE, etc. - Parse and store these details (e.g., in your parent app's state).
- As soon as the iframe loads, it sends
- User Interaction in the Parent
-
When a user selects a different product from your UI:
-
The configurator reloads to that product and returns updated messages (price, SKU, etc.).
-
- Configurator Updates
- On any selection change, the configurator posts back
CURRENT_PRICE,CURRENT_SKU, etc. - Update your parent UI or e-commerce logic accordingly.
- On any selection change, the configurator posts back
- Special Actions
- AR:
ENTER_ARleads to a WebXR session on Android or anAR_PREVIEW_LINKfor iOS. - Dimensions: Toggle rendering of dimension helpers on or off via
VIEW_DIMENSIONS.
- AR:
9. Example Minimal Code
Below is an extremely simplified example (plain HTML + JS) showing a typical integration:
10. Tips & Troubleshooting
- Cross-Origin: Ensure you have the correct CORS or target origins set.
- Performance: Since real-time 3D rendering can be resource-intensive, consider deferring the iframe load until it's needed, or show a placeholder until loading completes. A good idea can be showing an image of the product, then when the user selects a configuration item switching to the iframe. This way the iframe will have already loaded in the second or two it takes them to make a selection, hiding the loading state.
- AR/VR Compatibility: The
ENTER_ARandENTER_VRfeatures rely on the browser's WebXR implementation. Unsupported devices may fall back to returning anAR_PREVIEW_LINK. - Event Parsing: Always wrap
JSON.parse(payload)in a try/catch block to handle any unexpected responses gracefully. - Product Switches: After sending
SELECT_PRODUCT, wait until you receive an update before updating the UI, as our system debounces updates.