Product lifecycle
A product becomes try-on-capable in three steps, and they have to happen in this order.
1. Create it with a category
Section titled “1. Create it with a category”curl -X POST https://api.integration.tryonvirtual.com/v1/products \ -H "Authorization: Bearer tryon_sk_your_key" \ -H "Content-Type: application/json" \ -d '{"title": "Aviator Sunglasses", "category": "eyewear"}'category drives which AI model processes the product — it’s required on create and can’t be
left unset later. Valid values: eyewear, watch, shoes, jewelry, clothes, bag,
luggage.
2. Add images
Section titled “2. Add images”curl -X POST https://api.integration.tryonvirtual.com/v1/products/{id}/images \ -H "Authorization: Bearer tryon_sk_your_key" \ -H "Content-Type: application/json" \ -d '{"url": "https://yourstore.com/images/aviator.jpg"}'This is the step that actually triggers processing — a product with no images can never become
ready, no matter how you set mode or tryon_enabled. You can also pass images directly in
the create call in step 1; either way works. See Images for URL vs.
multipart upload, size/format limits, and per-image failure codes.
3. Enable try-on
Section titled “3. Enable try-on”curl -X PATCH https://api.integration.tryonvirtual.com/v1/products/{id} \ -H "Authorization: Bearer tryon_sk_your_key" \ -H "Content-Type: application/json" \ -d '{"mode": "swap", "tryon_enabled": true}'Enabling requires a category (already set in step 1) and a mode. Changing mode on a
product that already has try-on enabled turns it off again — you’ll need a fresh
tryon_enabled: true after switching modes.
Polling swap_ready
Section titled “Polling swap_ready”swap_ready on the product reports whether the images have finished processing for AI try-on.
It’s independent of tryon_status — you can enable try-on before processing finishes, and
swap_ready will flip to true on its own once the pipeline catches up.
Poll GET /v1/products/{id} every few seconds after adding images; processing is usually done
in under a minute.
curl https://api.integration.tryonvirtual.com/v1/products/{id} \ -H "Authorization: Bearer tryon_sk_your_key"If swap_ready stays false for more than a few minutes, the images likely failed rather
than being slow:
- Check the
images_failedarray returned by the originalPOST /v1/products(or the error response of thePOST /v1/products/{id}/imagescall you used) — a URL that timed out, wasn’t reachable, wasn’t actually an image, or was over 15 MB is reported there, not silently retried. - Look at the product’s
imagesarray — if it’s empty, none of your URLs succeeded and there’s nothing for the pipeline to process. Add a working image URL to retry. - See Images for the full list of per-image error codes and what each one means.
tryon_status vs. swap_ready
Section titled “tryon_status vs. swap_ready”These are two independent gates, and the storefront button should only render when both are satisfied:
| Field | Meaning |
|---|---|
tryon_status |
Whether you’ve turned try-on on for this product (active / inactive) — set via PATCH |
swap_ready |
Whether the AI engine has finished processing the product’s images |
A product can be active with swap_ready: false (you enabled it before processing finished)
— rendering the button in that state opens an empty experience for the customer. Always check
both before you decide whether to show the button when generating your product pages — see the
storefront snippet in the quickstart.
mode: realtime vs. swap
Section titled “mode: realtime vs. swap”swap (AI photo swap) is the mode you can drive end-to-end through this API — create, add
images, enable, done.
mode: realtime is the AR experience, and it requires a 3D asset. 3D assets are managed in the
merchant panel (upload or AI generation) — this API can’t
attach one. Enabling realtime mode requires an active 3D asset: PATCH {"mode": "realtime", "tryon_enabled": true} returns 400 validation_error (“Active 3D asset required for real-time
mode”) if none is usable. If the product has exactly one eligible 3D asset, it’s activated
automatically and the enable succeeds — otherwise, activate one in the panel first and check
active_asset_id on the product (non-null means one is active) before you PATCH.
Mapping to your catalog
Section titled “Mapping to your catalog”Every product has an id we generate — store it as the join key if that’s easiest for your
integration. Or set external_id to your own SKU or database id at create time (or via a later
PATCH):
curl -X POST https://api.integration.tryonvirtual.com/v1/products \ -H "Authorization: Bearer tryon_sk_your_key" \ -H "Content-Type: application/json" \ -d '{"title": "Aviator Sunglasses", "category": "eyewear", "external_id": "SKU-1234"}'external_id is unique within your shop. Once it’s set you can:
- Filter with
GET /v1/products?external_id=SKU-1234 - Use
SKU-1234directly asPRODUCT_IDin the storefront snippet instead of ourid— your templates never need to know our ids at all
external_id is read-only for shops on the Shopify platform (Shopify sync owns that mapping
there) — this field is for WooCommerce, custom platforms, and other non-Shopify shops.
Images — URL vs. multipart upload, limits, and error codes.