3D embeds
Showing the piece itself, not only its data — and why that uses a different credential.
Two credentials, two directions
This API is server-to-server and returns product data. The 3D viewer is the opposite: it runs in your visitor’s browser and returns product geometry. They therefore authenticate differently, and the secret key must never appear in the page.
The embed uses your public dyj_live_ key, which is safe to ship to a browser because it only works on the domains you have authorised in your DYJ account. Add every storefront domain there before going live, including staging.
Placing a viewer
Two things are the same for every product and live in your dashboard: your public dyj_live_ key and the viewer script tag (both under My Account → Developer, and in any embed code shown there). Keep them in your store’s configuration. Every product in a search or detail response then carries an embed object with the two per-product URLs. Render them into two tags — the URLs already carry your public key:
<div class="dyj-viewer"
data-license-key="{{ DYJ_PUBLIC_KEY }}"
data-config-url="{{ product.embed.configUrl }}"
data-poster-url="{{ product.embed.posterUrl }}"></div>
<script async src="{{ DYJ_VIEWER_SCRIPT_URL }}"></script>Guard the poster line: posterUrl is null when the piece has no poster, and a template that prints it unguarded emits data-poster-url="null" — a request for an image called null. Leave the attribute out instead. And render both URLs from data, not from a saved copy: photo and poster URLs change when the designer updates the piece, so take them fresh from each sync rather than hard-coding them.
One script tag per page is enough; it initialises every .dyj-viewer element, including ones added later. The poster paints immediately and crossfades to the 3D view when it is ready. Reviewed specification offers display only the approved appearance; additional material swatches are unavailable. Legacy products keep their existing variations.
embed is null only when your account has no viewer key yet. Generate one under My Account → Developer; it is not a secret. If you regenerate it later, update your store’s configuration — the URLs in the API follow the new key by themselves, the attribute in your page does not.
Photographs
photos is the product gallery in display order. Each url is a stable public image URL: it carries no key, is served with long-lived caching (a changed image gets a new URL rather than a new version of the old one), and can go straight into an <img src> or a CDN. The same goes for embed.posterUrl, which is null when the designer’s published version has no poster — fall back to the first photo, or leave the data-poster-url attribute off. Whether a product is still yours to sell is answered by this API, not by its pictures: take the buy button away when a sync no longer returns it. Each photo also carries a category — for images the designer generated in DYJ Studio it is the mode they chose (product_shot, try_on, lifestyle_scene, campaign_shot); uploaded photographs, renders and the 3D poster say so (product_photo, render, poster). Group by it, or pick a hero image from a category you prefer.
Render from a fresh response
Take embed and photos from the same sync that gave you the price. The 3D model behind the viewer is protected against copying with links that refresh on their own; the viewer handles that transparently, but a configUrl copied into a static template months ago is still fine only because it carries no expiry — the model it points at is re-checked each time. Keep the tag, refresh the data.
When a product goes away
A viewer whose product has left your feed — delisted, blocked by its designer, no longer matching your rules, or a plan that lapsed on either side — does not error and does not show a broken frame. It renders the poster with a neutral, quiet notice, because the person looking at it is your customer, not ours, and a stack trace on your product page helps nobody. A viewer on a domain you have not authorised, or one pointed at a product outside your feed, refuses outright.
Your own page should do the same: if a sync no longer returns a product, take the buy button away before you take the picture away.
What the viewer never exposes
The model served to browsers is a display-resolution derivative in a container no standard tool opens, keyed per hour; the manufacturing file never leaves DYJ. This is protection against casual copying, not a guarantee — anything a browser renders can in principle be captured, which is why the display mesh carries no manufacturing value.