Upload a finished model
Bring your own 3D file with model_url - Viewrium converts it to GLB and hosts the viewer.
If you already have a 3D model, you do not need to generate one. Pass a model_url and Viewrium
converts it to GLB, stores it, and gives you the same hosted 3D/AR viewer, embed, and analytics as
a generated model. The analysis and the pipeline are skipped entirely - this is a fast,
store-only path.
Supported formats
model_url must point at a hosted 3D file in one of these formats:
glb, gltf, obj, stl, ply, dae
A .glb is validated and stored as-is; the other formats are converted to GLB for you.
Request
from viewrium import ModelDimensions, ProductCreateRequest, ProductDraft, Viewrium
client = Viewrium("sk_live_...")
product = client.products.create(
ProductCreateRequest(
model_url="https://cdn.example.com/models/oak-chair.glb",
draft=ProductDraft(
title="Oak dining chair",
dimensions=ModelDimensions(height=92, width=45, depth=52), # cm
),
)
)
# `model_url` never parks, so this is a Product.
print(product.id, product.display_status)import { Viewrium } from "@viewrium/sdk";
const client = new Viewrium({ apiKey: "sk_live_..." });
const product = await client.products.create({
model_url: "https://cdn.example.com/models/oak-chair.glb",
draft: {
title: "Oak dining chair",
dimensions: { height: 92, width: 45, depth: 52 }, // cm
},
});Notes
- It never parks. A finished GLB has nothing to analyze and nothing to price, so
createcommits immediately and returns the product (HTTP 202) while conversion and storage run. There is noresume_tokenon this path andoverridesdo not apply. - No catalog images.
model_urlorders the model half only - the product has a model and no image positions. Order images for it afterward withproducts.order. - Set
dimensions(any one to three axes, cm by default - sendunitfor anything else) so the model displays at true size in AR. You can also re-scale later withproducts.rescale. - The file must be publicly reachable so Viewrium can fetch it.
Then
Wait for display_status to leave generating by
polling or webhooks;
product.model.glb_url then points at the stored, converted GLB (not your original URL). Publish
the product and embed it with the <viewrium-model> component.
Ordering the missing half
products.order asks for what the product does not have yet - images onto a model-only product, or
a model onto an images one. Like a create, it parks: the additions come back priced, inside a
token that products.create commits.
from viewrium import ProductOrder, ProductOrderRequest
parked = client.products.order(product.id, ProductOrderRequest(order=ProductOrder(images=True)))
print(parked.cost.total_credits)
client.products.create(ProductCreateRequest(resume_token=parked.resume_token))const parked = await client.products.order(product.id, { order: { images: true } });
await client.products.create({ resume_token: parked.resume_token });Re-scaling an existing model
Already have a stored model and just need to fix its real-world size? Use products.rescale - it
rewrites the stored GLB in place (the URL stays the same) and returns the product with the
dimensions it actually achieved.
from viewrium import DimensionUnit, ProductRescaleRequest
client.products.rescale(product.id, ProductRescaleRequest(height=92))
# or in another unit - stored dims stay cm either way
client.products.rescale(product.id, ProductRescaleRequest(height=36, unit=DimensionUnit.IN))await client.products.rescale(product.id, { height: 92 });
await client.products.rescale(product.id, { height: 36, unit: "in" });Uploaded files are the one case where Viewrium cannot tell which way the model faces - there are no
product photos to read it from. If you set both width and depth and they come out swapped, say
which horizontal axis the width belongs to with
width_axis:
from viewrium import ProductRescaleRequest, WidthAxis
client.products.rescale(
product.id, ProductRescaleRequest(width=160, depth=90, width_axis=WidthAxis.X)
)await client.products.rescale(product.id, { width: 160, depth: 90, width_axis: "x" });