v1

Virtue Mirage — API & SDK

AI virtual try-on and sizing for any storefront — Shopify, BigCommerce, Magento, headless, or custom. One engine, many stores: a shopper's digital twin is network-wide, so an avatar built on one store works on all of them.

1. Get a key

In your Virtue Mirage dashboard, open Settings → API Key. There are two key types:

KeyUseWhere
vm_live_… secretFull access. Server-side only — never put it in a browser.Backend / server-side REST calls
vm_pub_… publishableBrowser-safe. Only works from the storefront origins you register.The drop-in <script>, browser bundles

Send the key as Authorization: Bearer <key> or X-VM-Api-Key: <key>.

2. Drop-in script (fastest)

Best for BigCommerce, Magento, or any themed store. Paste one tag, then call the helpers. Add your storefront origin under Settings → API Key first, or the publishable key won't be authorised.

<script src="https://virtue-brain-534746878054.us-central1.run.app/sdk/virtue-mirage.js"
        data-vm-key="vm_pub_xxx"></script>
<script>
  VirtueMirage.setCustomer('shopper@example.com');

  // Show "Your size: M" in a container
  VirtueMirage.mountSizeBadge('#vm-size', {
    gender: 'women', heightCm: 168, weightKg: 64, category: 'tops'
  });

  // Add a "See it on me" button that renders on the shopper's avatar
  VirtueMirage.mountTryOnButton('#vm-tryon', {
    productId: '123',
    productImage: 'https://cdn.example.com/products/123/front.jpg'
  });
</script>

Lower-level calls are available too: VirtueMirage.getSize(), .avatarStatus(), .preRender(), .tryOn() — all return Promises.

3. Headless / server-side (REST)

Best for headless / React / Next / Vite, or a backend. The API is plain REST — call it with fetch (Node 18+, or any HTTP client) using your secret key on the server. No package to install.

const BASE = 'https://virtue-brain-534746878054.us-central1.run.app';
const headers = { 'Authorization': `Bearer ${process.env.VM_SECRET_KEY}`, 'Content-Type': 'application/json' };

// Size + Fit Advisor
const size = await fetch(`${BASE}/api/v1/public/size`, { method: 'POST', headers,
  body: JSON.stringify({ gender:'women', heightCm:168, weightKg:64, category:'tops' }) }).then(r => r.json());

// Does this shopper already have a digital twin? (network-wide)
const twin = await fetch(`${BASE}/api/v1/public/avatar-status?email=shopper%40example.com`, { headers }).then(r => r.json());

// Render a product on the shopper's avatar (cache-first, 1 token per render)
const tryon = await fetch(`${BASE}/api/v1/public/tryon`, { method: 'POST', headers,
  body: JSON.stringify({ email:'shopper@example.com', productId:'123', productUrl:'https://cdn.example.com/products/123/front.jpg' }) }).then(r => r.json());

A typed npm package (@virtuemirage/sdk) wrapping these calls ships with our marketplace release — until then, the drop-in script and the REST endpoints above are the supported paths.

4. Endpoint reference

Method · PathPurposeTokens
POST /api/v1/public/sizeSize + Fit Advisor from measurements or height/weight/framenone
GET /api/v1/public/avatar-statusDoes this shopper have a digital twin? (network-wide)none
GET /api/v1/public/pre-renderFetch a stored try-on for a product + shoppernone
POST /api/v1/public/tryonRender a product on the shopper's avatar (cache-first)1 per render

POST /api/v1/public/size

curl -X POST https://virtue-brain-534746878054.us-central1.run.app/api/v1/public/size \
  -H "Authorization: Bearer vm_live_xxx" -H "Content-Type: application/json" \
  -d '{"gender":"women","heightCm":168,"weightKg":64,"category":"tops"}'

→ { "success": true, "size": "M", "confidence": "high", "category": "tops", "estimated": true }

Pass exact bust/waist/hips (with optional unit:"in") to override the estimate, or a productId to resolve category and the brand's size chart automatically.

GET /api/v1/public/avatar-status

curl "https://virtue-brain-534746878054.us-central1.run.app/api/v1/public/avatar-status?email=shopper@example.com" \
  -H "Authorization: Bearer vm_live_xxx"

→ { "success": true, "hasAvatar": true, "avatarUrl": "https://…",
    "brandOfRecord": "brand-a", "isNewToThisBrand": true }

POST /api/v1/public/tryon

curl -X POST https://virtue-brain-534746878054.us-central1.run.app/api/v1/public/tryon \
  -H "Authorization: Bearer vm_live_xxx" -H "Content-Type: application/json" \
  -d '{"email":"shopper@example.com","productId":"123","productUrl":"https://cdn.example.com/123/front.jpg"}'

→ { "success": true, "imageUrl": "https://…/tryon.jpg", "cached": false }

5. Errors

Status · codeMeaning
401 invalid_api_keyKey missing or unrecognised.
403 origin_not_allowedPublishable key used from an unregistered origin. Add it under Settings → API Key.
403 BLOCKED_KIDSChildren's products are never rendered — child-safety, no override.
409 NO_AVATARShopper has no digital twin yet (create one via onboarding).
429 TOKEN_LIMIT_EXCEEDEDBrand's monthly token allowance is spent.
Security: the secret key (vm_live_…) grants full, token-spending access — keep it on a server and out of source control. The publishable key (vm_pub_…) is the only key safe for the browser, and it only works from the origins you register.