Working with assets
- Last updated on May 15, 2024
- •
- 20-21 minutes to read
Customer's Canvas provides a number of APIs for working with the assets:
- Asset Storage API performs the CRUD operations on the assets in storage, just like you would with files on your local file system.
- Asset Processor API allows you to import assets to storage, validate them, and generate asset previews, for example, to display as thumbnails.
- Design Atoms API manipulates the Design Atoms model to create designs and edit the design model.
These APIs allow you to work with public assets (color profiles, designs, fonts, images, mockups, previews, resources) and the assets stored in private sources in the same way. In this topic, let's describe typical scenarios and find out how you can work with designs through the API.
Designs
Let's consider the following scenario. You have a number of design templates prepared by your artwork team. You want to let the user choose one of them, open it in the editor, modify it, and save a personalized copy. After that, you want to export the result as a JPEG or PDF file.
Here are some situations when this scenario makes sense:
- Creating digital images (i.e. not print products) - for example, personalized images for Instagram or Facebook marketing campaigns.
- As a part of the online ordering process, when the designs are not a part of the product catalog (i.e. a product is "Letter-size, 4/4, 80 lbs. cardstock" rather than "Wedding Invitation - Cherry Blossom template").
- As a part of a direct mail or other variable data printing scenario, when a user modifies a template by adding their own variable fields or other elements before populating it with a data.
No matter what the situation is, to implement this scenario, you need to solve these tasks:
- Add designs to storage.
- Display a list of designs.
- Load a specified design to the editor.
- Save a private design (i.e. a design personalized by a specific user).
Working with public templates is performed using the Designs group of endpoints. The PrivateDesigns group works with private designs stored in user's folders. Although we describe working with public assets here, private assets are handled by a similar set of endpoints.
Creating designs
To add designs to storage, you can create or import them first. When creating the designs, you can configure the design properties through the API. The Customer's Canvas API allows for creating blank designs and designs based on mockups or external resources that appear as a background.
Blank designs are suitable for users who create their products from scratch. They are free to add any design elements when the working area is limited by the canvas size and a bleed area, with validating that all the elements fit this area.
The endpoint DesignProcessor_CreateBlankDesign creates a design using basic settings and saves it to storage. The design name, path in storage, number of pages, and the page size are mandatory properties to be passed in the request body.
{
"designParams": {
"name": "Blank-letter",
"path": "letters"
},
"blankDesignSettings": {
"width": 792,
"height": 612,
"pages": 1
}
}
Note that the folders specified in the path
must already exist in storage. The width
and height
here are in pixels.
curl -X \
POST "https://dm-assetprocessor.azurewebsites.net/api/processor/v1/designs/blank" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d "{\"designParams\":{\"name\":\"Blank-letter\",\"path\":\"letters\"},\"blankDesignSettings\":{\"width\":792,\"height\":612,\"pages\":1}}"
When you have 3D mockups in DAE format, you can use them to create designs to be rendered on the products they represent. The endpoint DesignProcessor_CreateDesignFromMockup creates a design based on a specified DAE mockup and saves it to storage. This endpoint does not require any design parameters, since they will be taken from the mockup.
{
"designParams": {
"name": "Paper-bag",
"path": "packaging"
},
"mockupId": "6527afc63507abfadd355226"
}
The mandatory parameters are the design name, path, and mockup identifier.
curl -X \
POST "https://dm-assetprocessor.azurewebsites.net/api/processor/v1/designs/from-mockup" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d "{\"designParams\":{\"name\":\"Paper-bag\",\"path\":\"packaging\"},\"mockupId\":\"6527afc63507abfadd355226\"}"
Importing artworks
Another way to add designs to storage is to import artwork created in external tools, like Adobe Photoshop and InDesign. Such artwork may be created by professional designers and contain many design elements and document settings. In this case, you can also predefine how the design elements should behave in the editor.
The endpoint DesignProcessor_ImportDesign allows you to import artwork and save it to storage. The source file can be an internal Customer's Canvas state file or a graphic file in PSD or IDML format. If needed, you can generate a design preview with this endpoint.
curl -X \
POST "https://dm-assetprocessor.azurewebsites.net/api/processor/v1/designs/import" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: multipart/form-data" \
-F "sourceFile=@test-page.psd;type=image/psd" \
-F "previewSettings.makePreview=true" \
-F "previewSettings.width=300" \
-F "previewSettings.height=300" \
-F "previewSettings.name=thumbnail" \
-F "previewSettings.namespace=mystore"
After a design has been imported to storage, there may be situations that will not allow working with the design normally, for example, font files or data schemas may be deleted. In BackOffice, this can be noticed by the red icon on the design thumbnail, and its hasProblems
property will have the true
value. To get the details about such problems, use the endpoint DesignProcessor_Check.
curl -X \
POST "https://dm-assetprocessor.azurewebsites.net/api/processor/v1/designs/6551d8abef47c0b108dc75de/check" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>"
A response for a design with missing fonts may look as follows:
{
"fontMissingProblems": [
{
"postscriptName": null,
"name": "Roboto_Condensed"
},
{
"postscriptName": null,
"name": "Raleway"
}
],
"dataValidationProblems": [],
"dataSchemaMissingProblem": null
}
After you have changed a source design file, you can re-import the design to storage. The endpoint DesignProcessor_ReimportDesign is used when you need to replace a file without losing its metadata and ID. It will replace the design, its name, and file metadata, but the ID will remain the same. It is convenient when you are updating designs already associated with some products in your online store.
Arranging designs in folders
If you need different product categories, you can organize your designs into folders with the names of these categories. For example, you may have the following folder structure:
/Commercial Printing
/Business Cards
/Letter-size Flyer
/Tabloid-size Poster
...
Creating folders
The endpoint Designs_CreateFolder creates a single folder in the Designs asset section. To create a new folder /Commercial Printing/Business Cards, you need to make two request:
Create Commercial Printing in the root folder with the following request body.
{ "name": "Commercial Printing", "path": "/" }
Create Business Cards in Commercial Printing with the following request body.
{ "name": "Business Cards", "path": "Commercial Printing" }
curl -X \
POST "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs/folders" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d "{\"name\":\"Commercial Printing\",\"path\":\"/\"}"
To get the list of all folders in the Designs asset section, use the endpoint Designs_GetAllFolders. To retrieve the list of subfolders with their content, make a request to Designs_GetFolder. The endpoint Designs_Copy duplicates designs and folders.
Batch operations
The Asset Storage API allows you to perform batch operations on assets and folders:
When copying, you can assign new names to assets and folders. New elements will keep the metadata, however, they will get new IDs. Since original items stay intact, you need to perform deletion after copying to implement the move function.
The endpoint Designs_BatchCopy takes the following object in the request body.
{
"entityIds": [
"61790db31079e200f24ff92c", "652686bb3507abfadd354e83"
],
"folderIds": [
"6649a16e396239641d1b91dc"
],
"conflictStrategy": "Abort",
"path": "Cards"
}
To pass the folder identifiers, you can get them by getting the entire folder list with Designs_GetAllFolders or by path with Designs_GetFolder. The folder specified in path
must exist.
curl -X \
POST "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs/batch-copy" \
-H "accept: */*" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d "{\"entityIds\":[\"61790db31079e200f24ff92c\",\"652686bb3507abfadd354e83\"],\"folderIds\":[\"6649a16e396239641d1b91dc\"],\"conflictStrategy\":\"Abort\",\"path\":\"Cards\"}"
The endpoint Designs_BatchDelete also allows you to delete several assets and folders at once. In the request body, pass an object like this:
{
"entityIds": [
"6649c593396239641d1b920f", "6649c593396239641d1b9210"
],
"folderIds": [
"6649a0b1396239641d1b91db", "6649c592396239641d1b920e"
]
}
curl -X \
POST "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs/batch-delete" \
-H "accept: */*" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: application/json" \
-d "{\"entityIds\":[\"6649c593396239641d1b920f\",\"6649c593396239641d1b9210\"],\"folderIds\":[\"6649a0b1396239641d1b91db\",\"6649c592396239641d1b920e\"]}"
Conflict resolving strategy
When copying files and folders, there may be situations when there is an item with the same name in the destination folder. This results in an error. To resolve such errors automatically, a conflict resolving strategy was introduced. In the request parameters, you have already used the conflictStrategy
with the Abort
value, which aborts the request if the desired item name exists in the assets.
The following actions are available:
Abort
- the operation is canceled.Overwrite
- the existing file or folder is deleted, and a new one takes its place.Rename
- the existing file remains unchanged, and a unique name is generated for the new one.Skip
- operation is skipped for the existing file.
Design list
To get a list of designs in a storage, use the endpoint Designs_GetAll. This endpoint uses a tenantId
query parameter and returns the design list for a single tenant. However, if you don't specify it explicitly, then the tenantId
will be determined by your credentials.
curl -X \
GET "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>"
Filtering a design list
If you call this endpoint without any parameters, you will get all designs available in your tenant. However, you usually need to show a limited list of designs, e.g. only letter-size format or the designs belonging to a particular category. Let's take a look at the filtering options.
By folders
You may organize your designs in folders in accordance to the structure of your products or categories. For example, you may have folders like
/Commercial Printing
/Business Cards
/Letter-size Flyer
/Tabloid-size Poster
...
/Stickers
/Rectangular
/1x1
/2x2
/2x3
/3x3
...
/Ellipse
/1x1
/2x2
/2x3
...
In each folder, you will have designs for a specific size and product type.
When a user orders, say, a letter-size flyer, you need to use a path
parameter of Designs_GetAll and send /Commercial Printing/Letter-size Flyer
.
You may also send an includeSubfolders
parameter (true
or false
) to specify whether you need to return files only from this particular folder or select designs from subfolders.
curl -X \
GET "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs?path=%2FCommercial%20Printing%2FLetter-size%20Flyer&includeSubfolders=false" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>"
If you prefer to build a tree view and make the navigation similar to a file manager, you may prefer to use another endpoint - Designs_GetFolder. Unlike Designs_GetAll, you get not only a list of entries in a folder, but also a list of all subfolders. Also, this endpoint has fewer filtering features.
curl -X \
GET "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs/folders/content-by-path?fullPath=%2FCommercial%20Printing%2FLetter-size%20Flyer" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>"
By custom fields
Designs stored in Asset Storage support custom fields. You can add them through the endpoint Designs_Update. It allows for adding an arbitrary JSON object as a customFields
dictionary to any design, for example:
{
"Product Type": "Flyer",
"Category": "Retail"
}
curl -X \
PUT "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs/64df0541bc24c7f470b3c286" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>" \
-H "Content-Type: multipart/form-data" \
-F "customFields={\"Product Type\": \"Flyer\", \"Category\": \"Retail\"}"
Then, you may pass a JSON object that has been made into a string to the customFields
parameter to the Designs_GetAll endpoint to return only those values that match the specified fields. For example, to return all designs that have Product Type equal to Flyer, you need to pass the {"Product Type": "Flyer"}
string to customFields
.
curl -X \
GET "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs?customFields=%7B%22Product%20Type%22%3A%20%22Flyer%22%7D" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>"
By a part of a name
Sometimes you may want to have a search bar where the user can type in a name and narrow down a list of designs to only those that contain a specified text as a part of the design name. To do this, use the search
parameter of the Designs_GetAll endpoint.
curl -X \
GET "https://dm-assetstorage.azurewebsites.net/api/storage/v1/designs?search=flyer" \
-H "accept: application/json" \
-H "Authorization: Bearer <TOKEN>"
Design items
Each entry you receive using this API contains a number of fields, for example:
- ID
- Name
- Last modified date
- Custom fields
- ...and others
In addition, it contains the metadata, which is mainly used by Customer's Canvas internally. You may still find it useful, for example, how many surfaces (pages) it has or what are the dimensions of the design.
It also includes a link to a preview - a crucial element for every design browser interface. We will discuss them in the next section.
Previews
Some assets, like designs, images or fonts, may have previews. Previews are generated only once, and information about them is automatically added to the asset metadata. If you update an asset file (for example, modify the design), the preview is invalidated and automatically removed.
Each asset may contain more than one preview. For example, it may be a preview for an admin app or for a storefront, or perhaps a storefront app may require a small thumbnail and a larger preview.
"previews": {
"<namespace>-<name>": {
"id": "6064221fe810853799cbf2f3",
"name": "<name>",
"namespace": "<namespace>",
"width": 248,
"height": 141,
"url": "<URL>"
}
}
Here, the <namespace>
is a unique application name, for example, online-store
, backoffice
, mystore
, etc. The <name>
specifies a preview type (like thumbnail
, websized
, tiny-icon
, etc.).
To make Customer's Canvas generate a preview, you need to use the Asset Processor API. It has the endpoint DesignProcessor_PreparePreview, where you can specify the namespace
, name
, width
, height
and some other parameters, and then it will generate the preview and update the metadata.
curl -X \
GET "https://dm-assetprocessor.azurewebsites.net/api/processor/v1/designs/617a4fdd1079e200f24ffeb2/preview/mystore/thumbnail/160x120" \
-H "accept: application/octet-stream" \
-H "Authorization: Bearer <TOKEN>"
You don't have to re-request a design element after that. This endpoint returns a preview as a stream that can be sent to a browser right away. Also, there is a version of this endpoint that returns the result as a URL - DesignProcessor_PreparePreviewUrl.
This way, the workflow is the following:
- Request a design entry.
- Check whether the
metadata.preview["<your_namespace>-<preview_name>"]
is not empty. - If you find the preview information, read its
url
property and insert the acquired URL into the<img>
tag. - Otherwise, send a request to Asset Processor and use its output instead of the URL extracted from metadata. Customer's Canvas will automatically add preview information to the design metadata, and it will be recognized the next time Step 2 is performed.
Editor
We now have a page displaying a list of designs we need. Next, you want to allow a user to click on a thumbnail and open the appropriate design in an editor.
This is how you do it:
- Prepare an HTML page where the editor should be hosted.
- Integrate one of our editors to this page.
- Create a config for the editor where you will pass a design ID and other settings.
Depending on your needs, you can display the editor at the same page with a list (e.g. the editor may be opened in a popup dialog) or a separate page.
For details regarding the integration, refer to the Design Editor and Simple Editor articles.
Saving results
Fortunately, this part isn't complicated. The editors have a JavaScript method that allows for saving the result. When you do this, a private design is created in the Asset Storage. You receive its ID, which you can use to do the further operations:
- Generate a print file
- Insert Variable Data into the file
- Re-open it in the editor
- ...
Along with the private design (state) ID, you also receive URLs for the proof images and print files. If you just need to display a proof image (e.g. in a shopping cart) or download a PDF file, just use them without any additional APIs.
When working with the product model, you can serialize in to a design file by using DesignAtomsService_SaveProduct. This endpoint will generate a private design belonging to the user, who is working on it, and save it in that user's folder.
Retention policy
To clean up storage, the retention policy was implemented in BackOffice. Once a day, a background task that finds and deletes outdated assets for all tenants with EnableAssetsRetention
set to true
is performed on the backend. You can get this value for your tenant with the endpoint Tenants_Get
When creating a tenant, the value of the retention policy can be set to:
- Unknown
- Never
- Default
Assets are considered outdated if they meet one of the following conditions:
RetentionPolicy
is set toDefault
.LastAccessTime
is earlier than theAssetsRetentionPeriodInDays
defined in the tenant settings.
The default value of AssetsRetentionPeriodInDays
is set to 60
days. If AssetsRetentionPeriodInDays
is 0
, no cleanup is performed for the tenant.
To run this task through the API, use the endpoint Tenants_CleanUp.