---
title: "Designs and mockups | Customer's Canvas On-Premises"
canonical: "https://customerscanvas.com/docs/on-premises/design-editor/apis/designs-and-mockups/"
---

# Designs and mockups

> Design Editor provides a Web API to manipulate design and mockup files. This API works based on HTTPS requests and is handled by the `ProductTemplates` controller (**~/api/ProductTemplates**). It has the following functionality:

| Function | Request type | URL | Description |
| :--- | :--- | :--- | :--- |
| Upload a file | POST | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;** | Uploads a file to the `/designs/` or `/mockups/` folder. |
| Download a file | GET | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;?<wbr />downloadArchiveWithLinks=boolean&amp;<wbr />ext=string** | Downloads a file with the given ID. |
| Delete a subfolder | DELETE | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;** | Deletes a subfolder by ID. |
| Delete a file | DELETE | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;?<wbr />ext=string** | Deletes a file. Tries common extensions. |
| Replace a file | PUT | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;?<wbr />ext=string** | Replaces a file with the given ID. |
| Get a file list | GET | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups?<wbr />subfolder=string&amp;<wbr />ext=boolean** | Returns an array of file identifiers. |
| Get an image preview | GET | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;?<wbr />width=int&amp;<wbr />height=int&amp;<wbr />mode=File&#124;Design** | Returns an image preview with the given size. |
| Move or copy a file | PATCH | **~/api/<wbr />ProductTemplates/<wbr />designs&#124;mockups/<wbr />&#123;id&#125;?<wbr />path=&lt;newPath&gt;&amp;<wbr />name=&lt;newName&gt;&amp;<wbr />copy=boolean&amp;<wbr />overwrite=boolean&amp;<wbr />moveWithLinks=boolean&amp;<wbr />ext=string** | Moves or copies a file. |
| Get a design info | GET | **~/api/<wbr />ProductTemplates/<wbr />DesignInfo/<wbr />&#123;id&#125;** | Returns a list of spreads from IDML templates. |

## Headers

In the request header, this controller requires `X-CustomersCanvasAPIKey` - a unique API key defined in the [AppSettings.config](https://customerscanvas.com/docs/on-premises/design-editor/it-ops/config-backend/appsettings.md#ApiSecurityKey).

## URL Parameters

The `ProductTemplates` controller supports the following parameters:

-   `id` is the required parameter representing a file identifier. This identifier is the same one you normally use when loading a file into the Design Editor. It consists of a file name without an extension and, optionally, a path to the file relative to the **\\designs\\** or **\\mockups\\** folders. For example:
    -   `BusinessCard` is the `id` for the **\\assets\\designs\\BusinessCard.psd** file.
    -   `photobook\photobook_page_2` is the `id` for the **\\assets\\designs\\photobook\\photobook_page_2.psd** file.
-   `downloadArchiveWithLinks` enables archiving for the downloaded file. The default value is `false`.
-   `height` is the height of a file preview in pixels. This optional parameter is `500` by default.
-   `mode` allows you to specify in what way Design Editor generates design previews. If this parameter is `File` and there is a MergedImageFrame in your PSD file, then Design Editor returns this preview. Otherwise, the editor provides previews by rendering the designs. The default value is `File`.
-   `moveWithLinks` moves linked images with the referencing IDML template. The default value is `false`.
-   `subfolder` specifies a single subfolder from which you want to get a list of either designs or mockups. By default, all files with valid extensions are listed (`.idml`, `.psd`, `.png`, `.jpeg`, `.jpg`, `.svg`, `.pdf`, `.bmp`, `.tiff`, `.tif`, `.gif`, `.eps`, and `.ai`).
-   `ext` specifies a file extension.
-   `width` is the width of a file preview in pixels. This optional parameter is `500` by default.

When moving or copying files, you can omit `path`, `name`, or both parameters. If the `path` is not specified, then the destination folder is **\\designs\\** or **\\mockups\\**. If you omit the `name` parameter, the resulting file takes the same name as `id`.

:::important
The snippets below define the [API security key](https://customerscanvas.com/docs/on-premises/design-editor/apis/auth.md) in JavaScript code. It could be highly insecure if they are run on a public site. However, you can use them this way in your admin panel or just for demonstration purposes.
:::

## Sample of Uploading Designs

This sample displays a form that allows for selecting a file and a script that uploads this file to the **\\designs\\** folder on the server.

```html title="Sample of Uploading Designs"
<!DOCTYPE html>
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
    <script language="javascript">
        const baseUrl = "https://example.com/cc/api/ProductTemplates";
        const apiKey = "UniqueSecurityKey";

        const uploadTemplate = async (root, folder) => {
            const form = document.getElementById(root + "_upload");
            const data = new FormData(form);

            try {
                const response = await fetch(`${baseUrl}/${root}/${encodeURIComponent(folder)}`, {
                    method: "POST",
                    headers: { 
                        "X-CustomersCanvasAPIKey": apiKey 
                    },
                    body: data
                });

                if (!response.ok) {
                    throw new Error(`Server error: ${response.status}`);
                }

                const result = await response.json();
                console.log(`The ${result} file was uploaded successfully.`);
            } catch (error) {
                console.error("Upload failed:", error.message);
            }
        };
    </script>
</head>
<body>
    <div id="designs"></div>
    <hr />
    <h3>Upload a Design</h3>
    Folder: <input type="text" id="designfolder" />
    <form id="designs_upload" enctype="multipart/form-data">
        File: <input type="file" name="file" />
    </form>
    <input type="button" value="Upload Design" 
           onclick="uploadTemplate('designs', document.getElementById('designfolder').value)" />
</body>
</html>
```

## Example Requests

Here are several examples (one per each function provided by the `ProductTemplates` controller) illustrating how to form proper requests.

### Displaying a 250x250 pixels design preview

There is no need to form a request in JavaScript to get a design preview. For example, you can preview a `businesscard` design by using the following URL:

```js
<img src="https://example.com/cc/api/ProductTemplates/designs/businesscard?width=250&height=250" />
```

The other functionality requires properly formed requests. The examples in this topic use the following variables:

```js
// The absolute URL to the ProductTemplates controller.
var baseUrl = "https://example.com/cc/api/ProductTemplates";

// A unique application key defined in the AppSettings.config file;
// this key allows file operations (upload, download, delete, or replace).
var apiKey = "UniqueSecurityKey";
```

### Getting a list of all files in the \\assets\\designs\\ folder

```js
const getFileList = async () => {
  try {
    const response = await fetch(`${baseUrl}/designs`);
    
    if (!response.ok) {
      throw new Error(`Error: ${response.status}`);
    }

    const data = await response.json();
    
    //outputs the file list of files in the /designs/ folder to the console.
    data.forEach((id) => {
      const link = `/designs/${id}.psd`;
      console.log(link);
    });
  } catch (error) {
    console.error("Failed to get a file list:", error.message);
  }
};
```

If the `ext` parameter is omitted or `false`, then the response contains an array of strings representing file identifiers. Otherwise, the array elements contain identifiers and extensions in the following format:

```json title="Response with a file list"
[
    {
        "id": "businesscard2_side1",
        "ext": "psd"
    },
    {
        "id": "businesscard2_side2",
        "ext": "psd"
    }
]
```

### Deleting a page from the photobook

```js
const deleteFile = async () => {
  try {
    const response = await fetch(`${baseUrl}/designs/photobook/photobook_page_2`, {
      method: "DELETE",
      headers: { 
        "X-CustomersCanvasAPIKey": apiKey 
      }
    });

    if (!response.ok) {
      // Check for 4xx/5xx status.
      throw new Error(`Server error: ${response.status}`);
    }

    console.log("The file was deleted successfully.");
  } catch (error) {
    console.error("Failed to delete the file:", error.message);
  }
};
```

### Deleting the whole folder photobook

```js
const deleteFolder = async () => {
  try {
    const response = await fetch(`${baseUrl}/designs/photobook`, {
      method: "DELETE",
      headers: { 
        "X-CustomersCanvasAPIKey": apiKey 
      }
    });

    if (!response.ok) {
      // Check for 4xx/5xx status.
      throw new Error(`Server error: ${response.status}`);
    }

    console.log("The folder was deleted successfully.");
  } catch (error) {
    console.error("Failed to delete the folder:", error.message);
  }
};
```

### Uploading a mockup

```js
const uploadMockup = async (data) => {
  try {
    const response = await fetch(`${baseUrl}/mockups`, {
      method: "POST",
      headers: { 
        "X-CustomersCanvasAPIKey": apiKey 
      },
      body: data 
    });

    if (!response.ok) {
      // Check for 4xx/5xx status.
      throw new Error(`Server error: ${response.status}`);
    }

    const result = await response.json();
    // Outputs the ID of the uploaded mockup to the console.
    console.log("Mockup uploaded successfully. ID:", result);
  } catch (error) {
    console.error("Failed to upload the mockup:", error.message);
  }
};
```

The response contains the identifier of the uploaded file.

### Downloading a design template

```js
const downloadDesign = async () => {
  try {
    const response = await fetch(`${baseUrl}/designs/bbqinvitation`, {
      method: "GET",
      headers: { 
        "X-CustomersCanvasAPIKey": apiKey 
      }
    });

    if (!response.ok) {
      // Check for 4xx/5xx status.
      throw new Error(`Server error: ${response.status}`);
    }

    // Convert the response to a Blob.
    const data = await response.blob();

    // Create a temporary link to trigger the download.
    const a = document.createElement("a");
    const url = window.URL.createObjectURL(data);
    a.href = url;
    a.download = 'bbqinvitation.psd';
    document.body.append(a);
    a.click();

    // Clean up: remove the link and revoke the object URL.
    a.remove();
    window.URL.revokeObjectURL(url);

    console.log("The file download has started.");
  } catch (error) {
    console.error("Failed to download the design:", error.message);
  }
};
```

### Replacing a page in the photobook

```js
const replaceFile = async (data) => {
  try {
    const response = await fetch(`${baseUrl}/designs/photobook/photobook_page_2`, {
      method: "PUT",
      headers: { 
        "X-CustomersCanvasAPIKey": apiKey 
      },
      body: data 
    });

    if (!response.ok) {
      // Check for 4xx/5xx status.
      throw new Error(`Server error: ${response.status}`);
    }

    console.log("The file was replaced successfully.");
  } catch (error) {
    console.error("Failed to replace the file:", error.message);
  }
};
```
