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/ | Uploads a file to the /designs/ or /mockups/ folder. |
| Download a file | GET | ~/api/ | Downloads a file with the given ID. |
| Delete a subfolder | DELETE | ~/api/ | Deletes a subfolder by ID. |
| Delete a file | DELETE | ~/api/ | Deletes a file. Tries common extensions. |
| Replace a file | PUT | ~/api/ | Replaces a file with the given ID. |
| Get a file list | GET | ~/api/ | Returns an array of file identifiers. |
| Get an image preview | GET | ~/api/ | Returns an image preview with the given size. |
| Move or copy a file | PATCH | ~/api/ | Moves or copies a file. |
| Get a design info | GET | ~/api/ | 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.
URL Parameters
The ProductTemplates controller supports the following parameters:
idis 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:BusinessCardis theidfor the \assets\designs\BusinessCard.psd file.photobook\photobook_page_2is theidfor the \assets\designs\photobook\photobook_page_2.psd file.
downloadArchiveWithLinksenables archiving for the downloaded file. The default value isfalse.heightis the height of a file preview in pixels. This optional parameter is500by default.modeallows you to specify in what way Design Editor generates design previews. If this parameter isFileand 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 isFile.moveWithLinksmoves linked images with the referencing IDML template. The default value isfalse.subfolderspecifies 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).extspecifies a file extension.widthis the width of a file preview in pixels. This optional parameter is500by 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.
The snippets below define the API security key 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.
<!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:
<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:
// 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
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:
[
{
"id": "businesscard2_side1",
"ext": "psd"
},
{
"id": "businesscard2_side2",
"ext": "psd"
}
]
Deleting a page from the photobook
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
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
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
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
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);
}
};