Product Configurators

3D Product Configurator API: Events, State and Commerce Integration

A practical contract for moving validated configuration state between a 3D experience, pricing, saved designs, cart, orders and analytics without making the browser the source of truth.

A configurable coffee brewer sits beside a three-stage rail that separates command requests, resolved state and commerce commitment.
A reliable configurator API separates requested changes, accepted product state and commerce commitment.

A 3D product configurator API should keep one resolved configuration consistent across the interface, 3D scene, pricing service, saved design, cart and order. The browser may request a change, but the product rules and commerce services decide whether that change is valid and what it costs. The cart should receive a stable configuration reference, not trust whatever the canvas happens to show.

Build the integration around four explicit contracts: commands describe what a caller wants to change; resolved state records what is currently valid; domain events report accepted facts; commerce operations revalidate the state before price or cart commitment. Give each contract its own schema and version. This prevents an option click, a visual update and a completed cart action from being treated as the same event.

Treat resolved state as the product contract

The resolved state is the smallest record that can answer, "What product has this buyer configured, under which rules, at which revision?" It needs stable product and option identifiers, the selected values, calculated values that affect validity, a rule-set version, a configuration revision and a lifecycle status. Labels, thumbnails and mesh names can be projections of that record, but they should not replace it.

The broader 3D product configurator e-commerce integration blueprint covers product data, cart, order, analytics and production handoff as a whole. This guide stays at the API boundary: how those systems exchange intent, accepted state and evidence without becoming competing sources of truth.

Start by naming the authority for each field. A product information system may own public names and descriptions. A rules service may own compatibility. A pricing service may own a market-specific amount. The 3D runtime may own camera position, but it should not quietly become the authority for a sellable option. If the experience changes the product itself rather than only choosing which content a visitor sees, the distinction in e-commerce personalization versus product customization is worth settling before the API is designed.

Separate commands, state and events

Commands are requests. Use imperative names such as change-option, set-dimension, save-configuration and add-configuration-to-cart. A command can fail because the caller is unauthorized, the revision is stale, the option is incompatible or a required input is missing.

Events are accepted facts. Use past-tense names such as configuration.option-changed, configuration.validated, configuration.saved, price.resolved and cart.line-created. Do not publish option-changed merely because a control was clicked. Publish it after the rule service has accepted the change and assigned the resulting revision. The taxonomy below is Double Edged's editorial architecture, not a vendor standard.

One accepted brewer configuration feeds separate domain, commerce and telemetry lanes without letting analytics become product authority.
Domain facts, commerce commitments and analytics observations need separate contracts even when they start from one accepted revision.
Separate commands, state and events
FamilyExample namesWhat the record meansTypical consumers
Lifecycleconfigurator.ready, configuration.created, configuration.loadedA runtime or configuration reached a known lifecycle pointHost page, support tooling, observability
Configuration domainconfiguration.option-changed, configuration.invalidated, configuration.savedProduct state changed or failed a named rule under a known revisionUI, 3D adapter, save service, audit trail
Commerceprice.resolved, price.expired, cart.line-created, cart.line-rejectedA commerce service accepted or rejected a versioned stateStorefront, cart, quote service, order adapter
Operationalasset.load-failed, integration.unavailable, request.rate-limitedA technical dependency affected the experienceMonitoring, support, fallback logic
Analyticsconfigurator_started, option_selected, configuration_completedA measurement event was emitted for an agreed behaviorAnalytics pipeline only; never product-rule authority

A current vendor API will not necessarily use these names. As checked on 31 August 2026, Vectary's Model API documentation describes two-way website-to-scene events and connects event values to variables by name; if no matching variable exists, the documented result is undefined.[2] That is a useful integration surface, but it is also why a vendor adapter should translate scene events into your own versioned domain contract instead of letting a scene variable become a cart field by accident.

Give every event a versioned envelope

CloudEvents 1.0.2 is a vendor-neutral event format whose required context attributes are id, source, specversion and type.[1] A configurator does not have to adopt CloudEvents, but those fields are a good minimum for an event that must cross a viewer, storefront and backend.

Keep the envelope and project payload separate. In this example, seven project-defined identifiers sit inside data: configuration_id, configuration_revision, product_id, product_model_version, rule_set_version, correlation_id and causation_id. The schema named by dataschema should define every field. It should also say whether causation_id points to the command that produced the event or to an earlier event. changes carries the accepted change. These names belong to this example contract; the CloudEvents citation supports only the envelope attributes it names.[1]

This illustrative event uses the fields below. Dots show nesting, and the numeric segment marks the first item in the changes array.

Give every event a versioned envelope
Field pathExample valueMeaning in this example
idevt_01J_EXAMPLEUnique event identifier
typecom.example.configuration.option-changed.v1Versioned event type
source/configurator/storefrontEvent producer context
subjectconfig/cfg_2048/revision/12Configuration and revision addressed by the event
specversion1.0CloudEvents specification version used by the envelope
time2026-08-31T00:00:00ZExample occurrence time
dataschemahttps://api.example.com/schemas/option-changed/v1Schema for the data object
dataObjectProject-defined event payload
data.configuration_idcfg_2048Stable configuration identifier
data.configuration_revision12Accepted configuration revision
data.product_idproduct_310Stable product identifier
data.product_model_version2026.08.31Product-model version used to resolve the state
data.rule_set_version2026.08Rule-set version used to validate the change
data.correlation_idsession_84cProject-defined correlation identifier
data.causation_idcmd_01J_EXAMPLEProject-defined identifier for the direct cause
data.changesOne-item arrayAccepted changes carried by this event
data.changes.0.option_idfinishChanged option identifier
data.changes.0.value_idoxide-blueAccepted value identifier

CloudEvents says an incompatible data-schema change should use a different dataschema URI. It also warns that sensitive information should not be carried in context attributes because intermediaries may inspect or log them.[1] Keep email addresses, free-text personalization and access tokens out of event metadata.

Validate envelopes and command payloads before they reach business logic. JSON Schema's 2020-12 validation vocabulary can assert structure with keywords such as type, enum and required.[3] Schema validation catches malformed structure; the rule engine still has to decide whether a structurally valid choice is allowed for this product and revision.

Follow one commerce-safe sample sequence

The sequence below keeps request, accepted state and commerce evidence separate. Endpoint names are illustrative. The useful part is the ownership and revision behavior.

A configurable brewer moves from a requested option through validation before the accepted state reaches a commerce commitment.
The browser requests a change; validated state, not the click or rendered scene, advances to commerce.
Follow one commerce-safe sample sequence
StepCaller and operationAccepted resultEvidence to retain
1. LoadHost requests product definition and configuration capabilitiesProduct definition, option IDs, rule-set version and API capabilitiesProduct and contract versions used to start the session
2. CreateHost sends POST /configurations with product and market contextconfiguration.created at revision 1Configuration ID, owner class, market and expiry policy
3. ChangeUI sends change-option with expected revision 1Accepted state at revision 2, or a typed rejectionCommand ID, prior revision, changed IDs and rule outcome
4. Project3D adapter receives revision 2 and updates materials, parts or dimensionsVisual acknowledgement for revision 2Asset-map version and any visible fallback or load failure
5. PriceStorefront requests a price for configuration revision 2price.resolved with a price reference, currency and expiryPricing authority, configuration revision and price reference
6. SaveSave service writes the validated snapshot conditionallyconfiguration.saved with a durable ID and revisionOwnership, visibility, schema versions and updated timestamp
7. Add to cartStorefront submits configuration ID, revision, quantity and an idempotency keycart.line-created, or a typed rejection after revalidationCart-line ID, accepted configuration revision and price reference
8. MeasureAnalytics adapter receives accepted domain and commerce eventsApproved analytics eventsConsent state, event version and non-sensitive identifiers

If two tabs start from revision 2, the first accepted write may produce revision 3. The second write must not overwrite it. Choose one concurrency contract and document it.

For an HTTP ETag mapping, return a strong ETag for the configuration representation and require If-Match on state-changing requests.[9] Use 428 Precondition Required if the client omits that required condition; RFC 6585 defines 428 as the origin requiring the request to be conditional and shows If-Match in its example.[4] When If-Match is present but its entity tag is stale, RFC 9110 says the origin must not perform the method and may return 412 Precondition Failed.[9] Return a stable problem code and, when authorization allows it, the current revision so the client can reload, compare or reapply the change.

An expected_revision field carried only in the JSON body is different. Document it as an application-level revision check, not an HTTP precondition.[9]

The estimator maps rules, assets, visualization, integrations, pricing, outputs and operating ownership into an explainable complexity profile. It does not generate a supplier quote; price and timing still depend on verified requirements and acceptance criteria.

Persist identity, revisions and ownership

A saved configuration needs more than a JSON blob. Store a stable configuration ID and immutable revision number, then record the product definition, rule set, selected option IDs, calculated values, asset mapping, market and currency context, lifecycle status and ownership. Keep a readable summary alongside the structured state so service and production teams can understand the order without reopening the original browser session.

Choose the lifecycle deliberately. A useful project-specific set might be draft, validated, priced, ordered, expired and archived. Those names are not universal. What matters is that the backend checks allowed transitions. A cart endpoint should not accept an expired draft merely because the frontend called the steps in the expected order.

In guidance checked on 31 August 2026, OWASP calls out out-of-order API execution and recommends server-side workflow-state validation rather than relying on frontend sequencing.[6] Apply that rule when an anonymous configuration is claimed by an account, when a saved design becomes a quote, and when a quoted revision becomes an order. Record who may read, change, share or duplicate each state.

A share URL should carry an opaque ID and, when the use case needs reproducibility, a revision. Do not put the full option payload, access token or customer text in the URL. A saved ID also gives the system somewhere to attach migrations when a rule set or product model changes.

Keep pricing and cart authority on the server

The 3D scene may display a price, but it should display a server result tied to a configuration revision. A price response should identify currency, market, quantity assumptions, tax treatment if relevant, expiry and the authority that calculated it. When any price-bearing choice changes, mark the old result stale rather than subtracting or adding browser-side deltas to an authoritative total.

At cart time, revalidate product availability, rule compatibility, revision and price. Store the configuration ID and accepted revision on the cart line, plus a human-readable option summary and the reference needed to reconstruct the price decision. Use an idempotency key for cart creation so a retry does not create a second line unintentionally; define the key's scope and retention in the contract.

Return errors as data the client can act on. RFC 9457 defines a machine-readable Problem Details format for HTTP APIs and the application/problem+json media type.[7] A configurator can extend that object with stable codes and safe fields for invalid_option, stale_revision, price_expired, not_authorized or cart_mapping_failed. The RFC also warns that problem details are not a debugging channel; do not expose stack traces, internal queries or secrets in detail.[7]

If pricing depends on guided selling, account terms, approval or quote-to-order work, the scope may have crossed into the territory covered by 3D product configuration software versus visual CPQ. Keep the configurator API responsible for its state contract rather than hiding an entire CPQ workflow inside one getPrice() call.

Secure the embed and API boundary

An embedded viewer often communicates with its host page through window.postMessage(). MDN recommends an exact targetOrigin, not *, when the receiver is known; it also says receivers should verify origin, possibly source, and the syntax of incoming messages.[5] Treat that check as the first gate, not as product authorization.

After origin and schema validation, the API still needs to verify that the caller may read or change this configuration. OWASP recommends HTTPS for secure REST endpoints and access control at every non-public endpoint.[6] Use short-lived, appropriately scoped credentials for browser calls. Keep server credentials out of scene variables, URLs and client bundles.

Define limits for payload size, command frequency and expensive operations such as dynamic geometry or generated documents. RFC 6585 defines 429 Too Many Requests and permits a Retry-After header.[4] A client should back off without discarding its local draft, while the server preserves enough correlation data to diagnose repeated failures without logging sensitive option content.

Keep analytics downstream of accepted state

Analytics should observe the product contract, not drive it. Emit a configuration event only after the corresponding command is accepted. Emit an add-to-cart measurement only after the cart service creates the line, not when a button receives a click.

Google's GA4 ecommerce documentation, last updated 19 August 2026, defines recommended events including add_to_cart, view_cart, begin_checkout and purchase, with products represented in an items array.[8] Map accepted configurator events into that commerce vocabulary where the semantics match. Keep configurator-specific diagnostics in a separate, documented namespace.

Send the minimum useful identifiers. A product ID, configuration type, market and revision class may be enough for operational analysis. Free-text engraving, account pricing, email addresses and private saved-design content do not belong in a general analytics payload.

Version the contracts independently

A single /v2/ route cannot describe every kind of change. Track the API contract version, event schema, product definition, rule set and asset mapping separately. A material-name change may only affect the 3D adapter. A retired option may require a saved-state migration. A pricing-rule change may leave the visual state untouched but invalidate an earlier price reference.

Prefer additive event changes when consumers can safely ignore new optional fields. Give breaking payloads a new schema identifier and test old and new consumers during a defined transition. Keep adapters at vendor boundaries: the storefront should not need to know whether a viewer calls a value selected_color, materialId or something else.

Document support windows and failure behavior. If an old saved revision cannot migrate automatically, return a clear state that preserves the original evidence and asks for review. Quietly replacing an unavailable component with the nearest current option changes the product and can turn a migration shortcut into an order error.

Test failure paths before launch

A configurable brewer sits between current and stale revision plates above one verification gate used to test conflict handling.
Stale revisions, duplicate commands and failed dependencies need explicit evidence before the API is ready for commerce.

Run the contract against a common product, a rule-heavy product and one awkward exception. Keep the expected API, visual, price, cart and audit outcomes together.

  1. Send a valid option command and confirm that state, 3D and summary use the same accepted revision.
  2. Send an incompatible option and confirm that no price or cart event reports success.
  3. Replay the same command ID and verify the documented idempotent result.
  4. If the HTTP mapping requires If-Match, submit one write without it and another with a stale validator; verify separate 428 and 412 recovery paths.
  5. Try to open and edit another user's private saved configuration.
  6. Send a valid-looking postMessage from the wrong origin and from the wrong frame.
  7. Expire the price reference between configuration and cart creation.
  8. Remove or retire a selected option after a design has been saved.
  9. Make the 3D asset fail while product state remains valid, then verify the visible fallback.
  10. Repeat a cart request after a network timeout and confirm that the accepted result is not duplicated.
  11. Upgrade one event consumer while another remains on the prior compatible schema.
  12. Inspect analytics and logs for private text, credentials and unbounded payloads.

Record pass, fail and workaround separately. A manual correction on every order is operating work, not an API pass. A visually correct scene paired with an unrecoverable cart reference is also a failure.

Decide what belongs in discovery

The reusable pattern is simple: commands request, rules resolve, events report, commerce revalidates and persistent revisions preserve evidence. The project-specific work lies in the product rules, pricing authority, account model, downstream systems, security boundary, asset behavior and order output. Those details cannot be inferred from a generic API diagram.

Spellexo is relevant as Double Edged's owned-product proof of product strategy, UX, 3D production, engineering, testing, launch and operation. It is not proof of a configurator rescue, migration, conversion lift, return reduction or a prospect's integration outcome.

When the representative-product test exposes a genuine custom integration, the custom 3D product configurator service is the commercial route for discovery and implementation. Bring the state fields, event consumers, pricing authority, commerce platform, authentication model and required order record. That is enough to turn an API discussion into a bounded technical scope.

Sources

  1. CloudEvents specification, version 1.0.2Cloud Native Computing Foundation CloudEvents project · accessed August 31, 2026
  2. Events for APIVectary · accessed August 31, 2026
  3. JSON Schema Validation: A Vocabulary for Structural Validation of JSONJSON Schema · accessed August 31, 2026
  4. RFC 6585: Additional HTTP Status CodesIETF / RFC Editor · accessed August 31, 2026
  5. Window: postMessage methodMDN Web Docs · accessed August 31, 2026
  6. REST Security Cheat SheetOWASP Cheat Sheet Series · accessed August 31, 2026
  7. RFC 9457: Problem Details for HTTP APIsIETF / RFC Editor · accessed August 31, 2026
  8. Measure ecommerceGoogle Analytics developer documentation · accessed August 31, 2026
  9. RFC 9110: HTTP SemanticsIETF / RFC Editor · accessed August 31, 2026