---
title: "Rendering preview mockups | Customer&#x27;s Canvas Hub"
canonical: "https://customerscanvas.com/docs/hub/dev-center/scenarios/product-images/rendering-preview-mockups/"
---

# Rendering preview mockups

> Learn how to find products in a storefront, get their options and variants, retrieve artworks, and render preview mockups for these assets.

You can create previews based on mockups imported into Customer's Canvas from Adobe Photoshop. This may be useful for such scenarios as creating galleries of product images described in the [Mockup-based product images](https://customerscanvas.com/docs/hub/dev-center/scenarios/product-images.md) topic and during the design personalization. In this topic, you can learn how to implement this.

## Using the API

This guide assumes that you are familiar with the principles of using the [Customer's Canvas API](https://customerscanvas.com/docs/hub/dev-center/api.md). If not, we recommend reviewing these articles first.

- [Design Atoms API Reference](https://customerscanvas.com/docs/hub/dev-center/api/design-atoms.md) - for an API overview and information about supported API Client libraries
- [C# API Client](https://customerscanvas.com/docs/hub/dev-center/api/clients/cs-api-client.md) - for a guide on integrating the C# API Client library to your .NET app

Before starting, ensure that your app has credentials to make API calls:

1. In your tenant, navigate to **Settings** > **External apps** and register your app.
2. In your app, implement the authentication as explained in the [Authentication in Customer's Canvas Hub](https://customerscanvas.com/docs/hub/dev-center/api/auth.md) article.

Your application passes the product ID or SKU defined in your system to Customer's Canvas.

Using this product data, Customer's Canvas finds the product by ID, searches for an option by SKU, and retrieves all linked preview mockups. For each product mockup, use the Design Atoms API to render a preview of the mockup with a design.

## Searching for mockups

Before rendering a preview, you first need to know the mockup ID. Customer's Canvas provides several ways to do this through the UI and API.

### BackOffice UI

You can view mockup IDs in your BackOffice tenant: navigate to the **Mockups** section, right-click a mockup, click **Properties**, and copy the ID.

![Getting a mockup ID through UI.](images/mockup-id.png)

### Asset Storage API

Another approach is to find mockup IDs through the [`Mockups`](https://customerscanvas.com/docs/hub/dev-center/api/asset-storage.md#tag/mockups) API. This API provides CRUD operations on mockups in a tenant.

Let's look at how to get a list of mockups and filter this list by product. For example, this request will return a list of mockups for products filtered by the `mug` name in your tenant. Since your app credentials are bound to your tenant, you can skip passing your tenant ID.

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storage/v1/mockups?search=mug" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storage/v1/mockups?search=mug
```

  
  

**cs**

```cs
var searchString = "mug"; // Set the search substring
var filteredMockupList = await mockupsApiClient.GetAllAsync(search: searchString);
```

  
  

**js**

```ts
var searchString = "mug"; // Set the search substring
var productBySku = _mockupsApiClient.getAll(null, null, null, null, null, null, searchString);
```

  
  

**python**

```python
searchString = "mug" # Set the search substring
response = requests.get("https://api.customerscanvashub.com/api/storage/v1/mockups?search=" + searchString, 
           headers={"Accept": "application/json",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

### Associated assets

#### Getting the entire product config

The Customer's Canvas APIs allow you to retrieve the entire configuration of PIM products defined in a tenant. To get details about all mockups associated with product variants, use the endpoint [`GET /api/storefront/v1/products/{id}/variant-mockups`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/products/GetProductVariantMockups) with no restrictions on variants. Its response will contain all the variants, and you will be able to implement a search through them and quickly switch between them in your app.

For example, this is how you can get URLs that link to all mockups of a product with ID `42`.

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/products/42/variant-mockups" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/products/42/variant-mockups
```

  
  

**cs**

```cs
var productId = 42; // Set your product ID here
var variants = await productsApiClient.GetProductVariantMockupsAsync(productId);
```

  
  

**js**

```ts
var productId = 42; // Set your product ID here
var variants = _productsApiClient.getProductVariantMockups(productId);
```

  
  

**python**

```python
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/products/42/variant-mockups", 
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

Instead of gathering all options, variants, and mockups in a single request and to process them in your app, you can send several requests to receive data in portions and process them as needed. This workflow will go through the following steps:

```mermaid
flowchart TB
    t0(Finding a product by SKU)
    t1(Finding a product by reference)
    t2(Getting product options)
    t3(Getting variants for option values) 
    t4(Getting mockups for a variant) 
    t0-->t2
    t1-->t2
    t2-->t3
    t3-->t4
```

#### Finding a product by SKU

To filter products by SKU, you can use the endpoint [`GET /api/storefront/v1/products`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/products/GetAllProducts) with the query parameter `sku`. Let's assume that your product in Customer's Canvas has SKU `mug-012`:

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/products?sku=mug-012" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/products?sku=mug-012
```

  
  

**cs**

```cs
var sku = "mug-012"; // Set your SKU here
var productBySku = await productsApiClient.GetAllProductsAsync(sku: sku);
```

  
  

**js**

```ts
var sku = "mug-012"; // Set your SKU here
var productBySku = _productsApiClient.getAllProducts(null, null, null, null, sku);
```

  
  

**python**

```python
sku = "mug-012" # Set your SKU here
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/products?sku=" + sku,
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

#### Finding products by reference

You specify these references through the user interface on the **Links** tab of a product in BackOffice.

To find a product by reference linking to a product in your system, use the endpoint [`GET /api/storefront/v1/product-references`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/productreferences/Get) and pass the identifiers of your storefront and reference. Let's assume that your product reference is `"mug-12"`, and the storefront ID for your app is `10045`. In this case, the request will look as follows:

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/product-references/ext/mug-12/product?storefrontId=10045" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/product-references/ext/mug-12/product?storefrontId=10045
```

  
  

**cs**

```cs
var reference = "mug-12"; // Set your reference ID here
var storefrontId = 10045; // Set the storefront ID for your app here
var productByReference = await productsApiClient.GetProductAsync(reference, storefrontId);
```

  
  

**js**

```ts
var reference = "mug-12"; // Set your reference ID here
var storefrontId = 10045; // Set the storefront ID for your app here
var productByReference = _productsApiClient.getProduct(reference, storefrontId);
```

  
  

**python**

```python
reference = "mug-12" # Set your reference ID here
storefrontId = 10045 # Set the storefront ID for your app here
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/product-references/ext/" + reference + "/product?storefrontId=" + str(storefrontId),
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

#### Getting product options

The Storefront API allows you to retrieve an option list of a single product using the endpoint [`GET /api/storefront/v1/products/{id}/options`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/products/GetProductOptions). For example, you can get options of product `42` as follows:

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/products/42/options" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/products/42/options
```

  
  

**cs**

```cs
var productId = 42; // Set your product ID here
var productOptions = await productsApiClient.GetProductOptionsAsync(productId);
```

  
  

**js**

```ts
var productId = 42; // Set your product ID here
var productOptions = _productsApiClient.getProductOptions(productId);
```

  
  

**python**

```python
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/products/42/options",
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

#### Getting variants for option values

After you have retrieved an option list, you can get product variants corresponding to these options.

A single product in your e-commerce system may have many options available to users. As a result, Customer's Canvas will create product variants that match all the possible combinations of option values. You can get this bunch of products by product ID through the [`GET /api/storefront/v1/products/{id}/variants`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/products/GetProductVariants). For example, if your `productId` is `42`:

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/products/42/variants" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/products/42/variants
```

  
  

**cs**

```cs
var productId = 42; // Set your product ID here
var variants = await productsApiClient.GetProductVariantsAsync(productId);
```

  
  

**js**

```ts
var productId = 42; // Set your product ID here
var variants = _productsApiClient.getProductVariants(productId);
```

  
  

**python**

```python
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/products/42/variants",
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

To limit the variant list, you can apply an option value filter to the list. This filter is a string representing a JSON object, where the key is an option identifier, and the value is one or more comma-separated identifiers of option values. You can find these identifiers in the response of [`GET /api/storefront/v1/products/{id}/options`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/products/GetProductOptions). For example, to filter variants by an option with ID `18894` and its value with ID `67221`, use the following object:

```json
{
  "18894": "67221"
}
```

Next, pass this filter as a query parameter in a GET request or as a parameter of the corresponding client method.

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/products/42/variants?options=%7B%2218894%22%3A%20%2267221%22%7D" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/products/42/variantsoptions=%7B%2218894%22%3A%20%2267221%22%7D
```

  
  

**cs**

```cs
var productId = 42; // Set your product ID here
var filter = "{'18894': '67221'}"; // Set your option ID and option value ID here
var variants = await productsApiClient.GetProductVariantsAsync(id: productId, options: filter);
```

  
  

**js**

```ts
var productId = 42; // Set your product ID here
var filter = "{'18894': '67221'}"; // Set your option ID and option value ID here
var variants = _productsApiClient.getProductVariants(productId, null, null, null, filter);
```

  
  

**python**

```python
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/products/42/variantsoptions=%7B%2218894%22%3A%20%2267221%22%7D",
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

#### Getting mockups for a variant

After you have received the product variants, you will need to get assets for them to create your product gallery by using the endpoint [`GET /api/storefront/v1/products/{id}/variant-mockups`](https://customerscanvas.com/docs/hub/dev-center/api/storefront.md#tag/products/GetProductVariantMockups).

For example, this is how you can get URLs that link to mockups of a single product variant with ID `687078`. Here, the product ID is `42`.

The request to get URLs that link to mockups:

  

**curl**

```bash
curl -X \
  GET "https://api.customerscanvashub.com/api/storefront/v1/products/42/variant-mockups?productVariantId=687078" \
  -H  "accept: text/plain" \
  -H  "Authorization: Bearer <TOKEN>"
```

  
  

**http**

```
GET https://api.customerscanvashub.com/api/storefront/v1/products/42/variant-mockups?productVariantId=687078
```

  
  

**cs**

```cs
var productId = 42; // Set your product ID here
var variantId = 687078; // Set the required variant ID here
var variants = await productsApiClient.GetProductVariantMockupsAsync(productId, null, variantId);
```

  
  

**js**

```ts
var productId = 42; // Set your product ID here
var variantId = 687078; // Set the required variant ID here
var variants = _productsApiClient.getProductVariantMockups(productId, null, variantId);
```

  
  

**python**

```python
response = requests.get("https://api.customerscanvashub.com/api/storefront/v1/products/42/variant-mockups?productVariantId=687078",
           headers={"Accept": "text/plain",
                    "Authorization": "Bearer <TOKEN>"})
print(f"Status Code: {response.status_code}, Content: {response.json()}")
```

  

## Rendering mockups

After you have received the product mockups, you can render them with the designs or other images by using an ID if they are in your tenant storage, as well as through their URL. To do so, use the endpoint [`POST /api/atoms/v1/designs/render-preview`](https://customerscanvas.com/docs/hub/dev-center/api/design-atoms.md#tag/designatomsservice/RenderDesignPreview).

In the body, this request expects a JSON object with the asset identifiers and rendering settings in the following format:

```json
{
  "imageUrl": "string",  // for example, "https://placekitten.com/800/500"
  "imageId": "string",   // for example, "65129fb5222f24bf460bca69"
  "ownerId": "string",   // for example, "6527afc635b52bfadd355226"
  "mockupId": "string",  // for example, "642e293dc46d098d64514607"
  "renderingConfig": {
    "width": 800,
    "height": 500,
    "fileFormat": "Jpeg",
    "fitMode": "Fit"
  }
}
```

This is how you can make a request.

  

**curl**

```bash
curl -X \
POST "https://api.customerscanvashub.com/api/atoms/v1/images/render-image-preview" \
-H  "accept: application/octet-stream" \
-H  "Content-Type: application/json" \
-H  "Authorization: Bearer <TOKEN>" \
-d '{
  "imageId": "62da700abb25c5477797d9cb",
  "mockupId": "642e293dc46d098d64514607",
  "renderingConfig": {
    "fileFormat": "Jpeg"
  }
}'
```

  
  

**http**

```http
POST https://api.customerscanvashub.com/api/atoms/v1/images/render-image-preview
Content-Type: application/json
Accept: application/octet-stream
{
  "imageId": "62da700abb25c5477797d9cb",
  "mockupId": "642e293dc46d098d64514607",
  "renderingConfig": {
    "fileFormat": "Jpeg"
  }
}
```

  
  

**cs**

```cs
// Set IDs of an image and mockup and define rendering params
var body = """
{
    "imageId": "62da700abb25c5477797d9cb",
    "mockupId": "642e293dc46d098d64514607",
    "renderingConfig": {
        "fileFormat": "Jpeg"
    }
}
""";
var preview = await designAtomsImagesApiClient.RenderImagePreviewAsync(body: body);
```

  
  

**js**

```ts
// Set IDs of an image and mockup and define rendering params
const body = {
    imageId: "62da700abb25c5477797d9cb",
    mockupId: "642e293dc46d098d64514607",
    renderingConfig: {
        fileFormat: "Jpeg"
    }
};
const preview = _designAtomsImagesApiClient.create(null, null, body);
```

  
  

**python**

```python
import requests
response = requests.post(
    'https://api.customerscanvashub.com/api/atoms/v1/images/render-image-preview',
    json={
        "imageId": "62da700abb25c5477797d9cb",
        "mockupId": "642e293dc46d098d64514607",
        "renderingConfig": {
            "fileFormat": "Jpeg"
        }
    },
    headers={
        "Content-Type": "application/json",
        "Accept": "application/octet-stream",
        "Authorization": "Bearer <TOKEN>"
    }
)
```

  

The resulting image will be passed as a stream.

### Rendering settings

In the `renderingConfig`, you can specify the following settings:
- `width` is the image preview width, in pixels.
- `height` is the image preview height, in pixels.
- `fileFormat` is the image preview file format, either `Jpeg` or `Png`. The default value is `Png`.
- `fitMode` is the mode describing how the image will be inserted into the placeholder in one of the following ways:
    - `Fit` uses the width and height to specify a rectangle the image is inscribed into.
    - `Shrink` is the same as `Fit`, but it resizes the image only if resize dimensions are smaller than image dimensions. This is the default value.
    - `Resize` uses the width and height to specify dimensions of the image after a resize without maintaining its proportions.
    - `Fill` proportionally resizes and crops the image. First, the image is resized so that the given rectangle is inscribed into the resized image. After that, the rectangle is centered on the resized image, and the image is cropped by the rectangle bounds.

Now, let's learn how you can pass assets to this endpoint.

### External artworks

You can pass a link to an image from the Internet in the request body, for example:

```json
{
  "imageUrl": "https://placekitten.com/800/500",
  "mockupId": "642e293dc46d098d64514607",
  "renderingConfig": {
    "width": 800,
    "height": 800,
    "fitMode": "Fit"
  }
}
```

### Artwork from a public gallery

When you store prints in **Assets** > **Images** in your tenant, then you can use them through their ID, for example:

```json
{
  "imageId": "62da700abb25c5477797d9cb",
  "mockupId": "642e293dc46d098d64514607",
  "renderingConfig": {
    "width": 800,
    "height": 800,
    "fileFormat": "Jpeg"
  }
}
```

### Artworks uploaded by end users

A user can only upload images to private storage associated with this user. "Private" means it has an owner and a special access policy.

To implement this scenario, you need to create a user session as described in the [Registering customers](https://customerscanvas.com/docs/hub/dev-center/api/storefront/register-customers.md) topic, upload private images through the endpoint [`POST /api/storage/v1/private-images`](https://customerscanvas.com/docs/hub/dev-center/api/asset-storage.md#tag/privateimages), and then pass the `imageId` and `ownerId` to render the mockups. The request body may look as follows:

```json
{
  "imageId": "65129fb5222f24bf460bca69",
  "ownerId": "6527afc635b52bfadd355226",
  "mockupId": "642e293dc46d098d64514607",
  "renderingConfig": {
    "width": 500,
    "height": 500
  }
}
```

### Private designs

Another use case when you may need to render a product preview is displaying a mockup with a design personalized in Customer's Canvas. Here, you will need the endpoint [`POST /api/atoms/v1/designs/render-preview`](https://customerscanvas.com/docs/hub/dev-center/api/design-atoms.md#tag/designatomsservice/RenderDesignPreview).

This endpoint uses a similar JSON object in its body and supports variable data to be applied to the design.

```json
{
  "designId": "string",  // for example, "64f97dd555334834ede11817"
  "ownerId": "string",   // for example, "John.Wood"
  "mockupId": "string",  // for example, "642e293dc46d098d64514607"
  "renderingConfig": {
    "surfaceIndex": 0,
    "width": 800,
    "height": 500,
    "fileFormat": "Jpeg"
  },
  "variableData": [
    {
      "name": "string",  // for example, "job title"
      "value": "string", // for example, "junior copywriter"
      "type": "string"   // one of "Text", "InString", "ImagePlaceholder", or "Image"
    }
  ]
}
```

For the personalized design, you need to pass the following data:
  - `designId` - an ID of a private state file created during the personalization.
  - `mockupId` - an ID of the mockup to be rendered.
  - `ownerId` - an ID of the user who personalized the design and owns this private state file.
