> ## Documentation Index
> Fetch the complete documentation index at: https://docs.genlook.app/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Create Try-On

> Request a virtual try-on combining a customer photo with a product

Create a virtual try-on job. Returns immediately with a `jobId`. Poll [Try-On Status](/docs/virtual-tryon/endpoints/try-on-status) for the result.

<Note>
  On JavaScript, the [`@genlook/storefront` SDK](/docs/virtual-tryon/sdk) is the recommended integration: it calls this endpoint for you, along with the rest of the try-on flow.
</Note>

With the SDK, one call starts the try-on and resolves when the image is ready, polling included:

```javascript SDK theme={null}
const { imageUrl, generationId } = await genlook.generate({
  userImageId: fileId,
  productId: "gid://shopify/Product/1234567890",
});
```

## Request

<ParamField body="userImageId" type="string" required>
  The `fileId` from a previous upload.
</ParamField>

<ParamField body="productId" type="string" required>
  Shopify product ID (`gid://shopify/Product/{id}`).
</ParamField>

<ParamField body="variantId" type="string">
  Shopify variant ID (`gid://shopify/ProductVariant/{id}`). Uses the default variant if omitted.
</ParamField>

<RequestExample>
  ```bash cURL theme={null}
  curl -X POST "https://api.genlook.app/storefront/v1/try-ons" \
    -H "Authorization: Bearer pk_your_key_here" \
    -H "X-Genlook-Anonymous-Id: anon_..." \
    -H "Content-Type: application/json" \
    -d '{
      "userImageId": "customer-media/acc_123/file_abc123xyz.jpg",
      "productId": "gid://shopify/Product/1234567890",
      "variantId": "gid://shopify/ProductVariant/123456"
    }'
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://api.genlook.app/storefront/v1/try-ons', {
    method: 'POST',
    headers: {
      'Authorization': `Bearer ${PUBLISHABLE_KEY}`,
      'X-Genlook-Anonymous-Id': anonymousId,
      'Content-Type': 'application/json',
    },
    body: JSON.stringify({
      userImageId: 'customer-media/acc_123/file_abc123xyz.jpg',
      productId: 'gid://shopify/Product/1234567890',
      variantId: 'gid://shopify/ProductVariant/123456'
    })
  });
  const result = await response.json();
  ```
</RequestExample>

## Response

<ResponseField name="jobId" type="string" required>
  Try-on job ID. Use it to poll status.
</ResponseField>

<ResponseField name="message" type="string" required>
  Status message or reason the try-on was blocked.
</ResponseField>

<ResponseField name="code" type="string">
  Present when the try-on was blocked:

  * `QUOTA_EXCEEDED`: Monthly quota reached
  * `RATE_LIMIT_EXCEEDED`: Too many requests
  * `BILLING_NOT_ALLOWED`: Plan expired
  * `PRODUCT_BLOCKED`: Try-on is disabled for this product
  * `CREATION_FAILED`: Job could not be created
</ResponseField>

<ResponseExample>
  ```json Success theme={null}
  {
    "jobId": "gen_xyz789abc",
    "message": "Try-on job created successfully"
  }
  ```

  ```json Blocked theme={null}
  {
    "jobId": "",
    "message": "Monthly try-on quota exceeded",
    "code": "QUOTA_EXCEEDED"
  }
  ```
</ResponseExample>

## Next Steps

1. Store the `jobId`
2. Poll [Try-On Status](/docs/virtual-tryon/endpoints/try-on-status) every 2 seconds
3. Display the result when status is `COMPLETED`
