3D Model Generator
Generator import endpoints are read-only server-to-server requests. They require the standard API headers, the embed:session:create scope and an active plan. Import authorization does not issue an editor session and does not consume its monthly allowance. Opening the editor uses the same monthlyEmbedTokenLimit counter as the other embedded tools.
Discover and import generator models
Use /model-generator/models to list available models with generators. The generator descriptor pins projectId, revision, configurationId, templateRevision, productId and productModel3dId. Follow its importPath to retrieve that exact source revision. Product asset manifests also expose generators and each model’s generator descriptor. Templates can be imported separately by configuration and revision.
Catalog filters
| Endpoint | Details |
|---|---|
/model-generator/models | Model list: name (or q), categoryId, scope (all, own, global), limit (1-50) and offset. |
/model-generator/catalog | Template catalog: generatorType, productId, audience, q, templateKey, configurationId, limit and offset. |
/model-generator/projects | Project list: configurationId, q, scope (all, own, global), limit and offset. The public proxy defaults scope to all. |
/model-generator/image-libraries/:kind/assets | Texture/background libraries: kind is texture or background; q, category and mapType filter the available assets. |
A project import contains the document, revision, template and a files manifest. Each file supplies a path under /v1/model-generator/; prepend /public-api when downloading it from Alter Product. Copy required files to your own storage and replace source references with local references. Import mannequins and texture libraries through their catalog endpoints; public-files is restricted to allowed resource paths, and templates must pass their configuration/revision access checks.
Example request (fetch)
// Server-side: uses alterFetch and authHeaders from the API connection guide.
const catalog = await alterFetch('/model-generator/models?' + new URLSearchParams({
scope: 'all', limit: '24', offset: '0'
}));
const selected = catalog.items[0];
if (!selected?.generator) throw new Error('Select an available generator model');
const importPath = selected.generator.importPath;
if (!importPath.startsWith('/v1/model-generator/projects/')) {
throw new Error('Invalid generator import path');
}
const bundle = await alterFetch(importPath.slice('/v1'.length));
for (const file of bundle.files) {
if (!file.path.startsWith('/v1/model-generator/')) {
throw new Error('Invalid generator file path');
}
const response = await fetch('https://alterproduct.com/public-api' + file.path, {
headers: authHeaders,
redirect: 'error'
});
if (!response.ok) throw new Error(`File download failed: ${response.status}`);
const bytes = new Uint8Array(await response.arrayBuffer());
// Persist bytes in your local storage; record the mapping from
// file.sourceHref / file.href to the resulting local file reference.
}
// Persist bundle.document, bundle.template and revision metadata locally.
// Import the related product asset and its textures/mockups as needed:
const product = await alterFetch('/assets/products/' + selected.generator.productId);
const mannequins = await alterFetch('/model-generator/mannequins');
console.log({ product, mannequins });Editor session and local storage
Create the editor session with tool: model-generator, a positive numeric toolId identifying the local generator project (not its UUID or WooCommerce product ID), and the allowed storefront origin. Do not pass designId, orderId, runtimeBindingId or cart fields for this tool. The generator project UUID is a separate identifier. Pass the returned token through the iframe handshake; runtime bootstrap returns the generator context with storageMode: wordpress_local.
// Server-side, after authorizing the merchant's access to this local project.
const localProjectId = 42; // Local generator project ID, not its UUID or WC product ID.
const session = await alterFetch('/embed/session', {
method: 'POST',
body: JSON.stringify({
tool: 'model-generator',
toolId: localProjectId,
origin: 'https://yourstore.com'
})
});
// The iframe receives session.token through ALTER_CUSTOMIZER_SESSION_READY.
// Do not put API credentials or the token in the iframe URL.
const bootstrapResponse = await fetch('https://alterproduct.com/public-api/v1/runtime/bootstrap', {
headers: { Authorization: `Bearer ${session.token}` }
});
if (!bootstrapResponse.ok) throw new Error('Generator bootstrap failed');
const context = await bootstrapResponse.json();
console.log(context);Example response
{
"runtimeBindingId": null,
"designId": null,
"productId": 42,
"toolId": 42,
"runtimeType": "model-generator",
"storageMode": "wordpress_local",
"parentOrigin": "https://yourstore.com"
}// Host page: WordPress returns a numeric toolId and a UUID in id.
const url = new URL('https://alterproduct.com/app/model-generator');
url.search = new URLSearchParams({
embedded: '1',
lng: 'en',
parentOrigin: window.location.origin,
toolId: String(localProject.toolId),
serverProjectId: localProject.id
}).toString();
// Optional: serverProjectRevision pins an existing saved revision.
iframe.src = url.toString();
// Install the authenticated handshake and storage bridge described below.
// Setting iframe.src alone does not authorize the editor or provide storage.Iframe messages used by the WordPress bridge
The WordPress plugin hosts the storage bridge and checks administrator or WooCommerce manager permissions. It validates the iframe origin, source window, nonce, request ID and allowed project paths. The bridge sends local reads and writes to /wp-json/alter-wc/v1/model-generator. API credentials stay on the server. A custom integration must implement equivalent authenticated storage handling; the public generator API does not save projects to Alter Product.
| Type | Description |
|---|---|
ALTER_CHILD_HELLO / ALTER_PARENT_ACK | Child starts the handshake with a nonce; parent acknowledges the same nonce. |
ALTER_CUSTOMIZER_INIT_SESSION / ALTER_CUSTOMIZER_SESSION_READY | Child requests a model-generator editing session; parent returns the authorized token. |
ALTER_MODEL_GENERATOR_REQUEST | Child sends requestId, nonce and request containing method, path, data and responseType. |
ALTER_MODEL_GENERATOR_RESPONSE | Parent replies with the same requestId and nonce, plus status, data, headers and any error. |
// Messages after ALTER_CHILD_HELLO / ALTER_PARENT_ACK agree on the nonce.
// Iframe -> parent:
const sessionRequest = {
type: 'ALTER_CUSTOMIZER_INIT_SESSION',
nonce: handshakeNonce,
payload: {
tool: 'model-generator', alterProductId: localProject.toolId, mode: 'edit'
}
};
// Parent -> iframe, after the server authorizes the merchant and issues a token:
const sessionReady = {
type: 'ALTER_CUSTOMIZER_SESSION_READY',
nonce: handshakeNonce,
token: session.token,
tool: 'model-generator',
cartKey: `model-generator:${localProject.id}`,
mode: 'edit',
localSession: false,
adminSession: true
};
// Send only to the validated iframe's exact origin and source window.
// An authorized token and successful bootstrap are still required.A save supplies expectedRevision, templateRevision, document and artifact references. It creates an immutable revision; a stale expectedRevision returns HTTP 409. WordPress stores metadata in its database and files in its uploads directory. JSON is compacted and compressed with gzip when compression reduces its size.
// Example message from the iframe; savedSnapshot and artifact IDs come
// from the generator. The host checks origin/source/nonce/project permissions.
const message = {
type: 'ALTER_MODEL_GENERATOR_REQUEST',
requestId: crypto.randomUUID(),
nonce: handshakeNonce,
request: {
method: 'POST',
path: `/pattern-generator/projects/${projectUuid}/revisions`,
data: {
expectedRevision: loadedRevision,
name: projectName,
templateRevision,
document: savedSnapshot,
references: { artifactIds: savedArtifactIds }
},
responseType: 'json'
}
};The “Use saved model in design” action publishes a complete saved revision to a linked design. Customers then see it through the existing Customizer, Configurator or Viewer with the usual product bindings and subscription checks. The generator editor remains a merchant tool. Order links retain the saved project/revision so later edits do not silently change past orders.