Skip to main content
Choose this approach when you want to build a completely bespoke try-on experience. You design the upload screens, loading states, and result displays, while Genlook’s backend quietly handles the AI generation.
The Genlook app block still needs to be installed in your Shopify theme (you can hide the built-in button). We use Shopify’s app proxy to securely authenticate your requests without requiring any API keys, but the proxy must be active.

Architecture

All requests route through your store’s Shopify app proxy, meaning authentication is handled for you automatically.
Base URL: https://your-store.myshopify.com/apps/proxy_genlook-x/public

End-to-End Example

Here is a minimal, vanilla JavaScript implementation tying the core endpoints together:
async function tryOn(photoFile, productId) {
  const base = '/apps/proxy_genlook-x/public';

  // 1. Ensure the store has credits
  const credits = await fetch(`${base}/check-credits`).then(r => r.json());
  if (!credits.allowed) throw new Error('No generation credits available');

  // 2. Upload the user's photo (using our 3-step signed-URL flow)
  const { uploadUrl, uploadKey } = await fetch(`${base}/prepare-upload`, {
    method: 'POST',
  }).then(r => r.json());

  await fetch(uploadUrl, {
    method: 'PUT',
    headers: { 'Content-Type': 'application/octet-stream' },
    body: photoFile,
  });

  const { fileId } = await fetch(`${base}/upload-complete`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ uploadKey }),
  }).then(r => r.json());

  // 3. Kick off the AI generation
  const { jobId } = await fetch(`${base}/fitting-room`, {
    method: 'POST',
    headers: { 'Content-Type': 'application/json' },
    body: JSON.stringify({ userImageId: fileId, productId }),
  }).then(r => r.json());

  // 4. Poll for the final result
  for (let i = 0; i < 60; i++) {
    const status = await fetch(`${base}/generation/${jobId}`).then(r => r.json());
    
    if (status.status === 'COMPLETED') return status.resultImageUrl;
    if (status.status === 'FAILED') throw new Error(status.errorMessage);
    
    // Wait 2 seconds before polling again
    await new Promise(resolve => setTimeout(resolve, 2000));
  }

  throw new Error('The generation request timed out');
}
If you’re using our SDK alongside your custom endpoints, you can use Genlook.cabin.fetch(url, options) instead of manually constructing the base proxy path. Read more about it in the Custom Button guide.

Endpoint Reference

Dive deep into the documentation for each specific endpoint:

Upload Image

Secure 3-step signed-URL flow for handling customer photos.

Create Generation

Request a new virtual try-on generation.

Generation Status

Poll the status of an ongoing generation.

Check Credits

Verify the store has enough credits before starting a job.

Collect Email

Securely pass collected customer emails to the Genlook backend.

Share Generation

Generate public, shareable links for try-on results.

Download Image

Safely download generated images without CORS issues.

Tracking Events

Fire custom analytics events back to the dashboard.

Error Codes

When things go wrong, error responses will include a message and optionally a specific code:
CodeMeaning
QUOTA_EXCEEDEDThe store has reached its monthly generation limit.
RATE_LIMIT_EXCEEDEDToo many requests were made in a short time.
BILLING_NOT_ALLOWEDThe store’s plan has expired or there is a billing issue.
CREATION_FAILEDThe generation job failed to initialize.