---
title: "State Files"
canonical: https://customerscanvas.com/docs/cc6/web-api-for-manipulating-states.htm
archived: true
applies_to:
  - product: "Customer's Canvas On-Premises"
  - product: "Design Editor"
    versions: ["6.15.0", "6.x (may differ)"]
---

**You’re viewing outdated documentation.** [View the latest Customer’s Canvas On-Premises documentation](https://customerscanvas.com/docs/on-premises/).

# State Files

**Applies to:** Customer's Canvas On-Premises; Design Editor 6.15.0, 6.x (may differ) · **Archived documentation**
 
Every time you call [saveProduct](https://customerscanvas.com/docs/cc6/customerscanvas.iframeapi.editor.saveproduct.htm.md) or [finishProductDesign](https://customerscanvas.com/docs/cc6/customerscanvas.iframeapi.editor.finishproductdesign.htm.md), Customer's Canvas creates a [state file](https://customerscanvas.com/docs/cc6/creating-templates-without-Photoshop.htm.md) representing all objects loaded in the editor. By default, these state files are saved in the `..\userdata\<someUserId>\states\` folder for a single user and they are kept forever until you delete these files manually. Customer's Canvas does not automatically clean them up. At the same time, you can use the Web API to manipulate state files in your application: list available state files, delete state files, reload images in state files from their original sources, and more.
 
This API works based on HTTPS requests and is handled by the **StateFiles** controller with the following methods:
 
|  Function |  Request type |  URL |
| --- | --- | --- |
   |  Get a list of user's state files |  GET |  `~/api/users/{userId}/states?page=number&items=number&extendedStateInfo=boolean` |
 |  Check if a state file is available |  HEAD |  `~/api/users/{userId}/states/{stateId}` |
 |  Upload a state file |  POST |  `~/api/users/{userId}/states/{stateId}` |
 |  Download a user's state file |  GET |  `~/api/users/{userId}/states/{stateId}` |
 |  Delete a user's state file |  DELETE |  `~/api/users/{userId}/states/{stateId}` |
 |  Copy and clone a state file |  POST |  `~/api/users/{userId}/states/{stateId}` |
 |  Modify a state file |  PATCH |  `~/api/users/{userId}/states/{stateId}` |
 |  Get product tags from a state file |  GET |  `~/api/users/{userId}/states/{stateId}/tags` |
 |  Get variable items from a state file |  GET |  `~/api/users/{userId}/states/{stateId}/variables` |
 |  Get the entire object model from a state file |  GET |  `~/api/users/{userId}/states/{stateId}/model` |
 
### URL Parameters
 
The **StateFiles** controller requires the following parameters:
 
- **userId**=[string] - a user identifier.
- **stateId**=[string] - a file name of a state without an extension.

You can also pass the following optional parameters when getting a list of state files:
 
- **page**=[number] is the number of the page to output. The default value is `null`.
- **items**=[number] defines the number of items per page. The default value is `null`.
- **extendedStateInfo**=[boolean] enables the output of such additional parameters as the surface count and product tags. If `false`, outputs only state IDs and timestamps. The default value is `true`.

When you pass both **page** and **items**, then the response headers will contain the number of **TotalPages** and **TotalItems**.
 
### Error Response
 
This controller can return the following errors:
 
- ```
    Status Code: 403 Forbidden
    Content: HTTPS Required
    ```
- ```
    Status Code: 403 Forbidden
    Content: Invalid Security Key
    ```
- ```
    Status Code: 404 Not Found
    Content: The specified state file cannot be found.
    ```
- ```
    Status Code: 400 Bad Request
    Content: This state already exists.
    ```
- ```
    Status Code: 500 Internal Server Error
    Content: The remote server returned an error: (404) Not Found.
    ```

It is recommended to [download a code sample](https://customerscanvas.com/docs/cc6/samples/StateFilesAPI.zip) written in ECMAScript 2015 that demonstrates how you can work with the API and refer to this sample when reading this topic.
 
**Important** 
The security model of Customer's Canvas requires you to pass [X-CustomersCanvasAPIKey](https://customerscanvas.com/docs/cc6/webapi.htm.md) in request headers. The snippets below define the API security key in JavaScript code. It could be highly insecure if it runs on a public site. However, you can use it this way in your admin panel, or just for demonstration purposes.
 
## Getting a List of a User's State Files
  
To get a list of state files, you can make the following request. If a user has many state files, it will display only the first 10 of them.
 
### Request Example
 
```
const userId = "default";
const url = `https://localhost:44300/api/users/${userId}/states?page=1&items=10`;
fetch(url).then(response => {
    return response.json();
}).then(json => {
    for (let i = 0; i < json.length; i++) {
        const s = json[i];
        console.log(s.stateId);
    }
});
```
 
### Success Response
 
For example, you will get the following response to this request when the **default** user has a state file.

```
Status Code: 200 OK
TotalPages: 1
TotalItems: 1
Content:
[{
  "stateId":"0777bb82-6f89-4e72-93b1-aad1b875602b",
  "dateModified":"5/26/2018 8:29",
  "surfaceCount":2,
  "tag":null
}]
```
 
## Checking If a User's State File is Available
  
To check if a user's folder contains a state file, you can make the following request.
 
### Request Example
 
```
var userId = "JohnWood";
var stateId = "1f190673-226d-4c31-87b4-0140805cc445";
var url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;

fetch(url, {
    method: "HEAD",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey"
    }
}).then(async function (response) {
    if (response.ok) {
        console.log("OK");
    }
    else {
        console.log("Not Found");
    }
});
```
 
### Success Response
 
When the state file is in the user's folder, this controller returns:

```
Status Code: 200 OK
```
 
## Uploading a State File
  
This method accepts a state file in the request payload and uploads this file to the `..\userdata\{userId}\states\` folder. When you pass the **stateId** parameter in your request, this identifier is assigned to the uploaded state file. When you omit **stateId**, this controller generates a new unique identifier and returns it in the response.
 
### Request Example
 
```
const userId = "JohnWood";
var formData = new FormData(document.querySelector("#state_to_upload"))

fetch("https://localhost:44300/api/users/${userId}/states/", {
    method: "POST",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey"
    },
    body: formData
})
.then(
    response => {
        console.log(response);
    }
);
```
 
### Success Response
 
When the state file has been successfully uploaded, this controller returns an ID of this state:

```
Status Code: 200 OK
Content: "d1ba8901-5884-4a2c-8e28-1463b6862fa9"
```
 
## Downloading a User's State File
  
### Request Example
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
logElement.textContent = "init request";

fetch(url, {
    method: "GET",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
        'Accept': 'application/json',
        "Content-Type": "application/json"
    }
})
.then(
    response => {
        if (response.ok) {
            console.log("The state file was downloaded successfully.");
            console.log(response.url);
        }
        else
            console.error("Failed to download the state file.");
    },
    e => console.error("Failed to download the state file.")
);
```
 
### Success Response
 
If the result is successful, this API returns a file stream:

```
Status Code: 200 OK
Content-type: application/octet-stream
```
 
## Deleting a User's State File
  
To delete a saved product from the `userdata` folder, you can make the following request.
 
### Request Example
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
fetch(url, {
        method: "DELETE",
        headers: {
            "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
            "Content-Type": "application/json"
        }
    })
    .then(
        response => { return response.json(); },
        e => console.log("Failed to delete the state file.")
    )
    .then(json => {
        if (json === true)
            console.log("The state file was deleted successfully.");
        else if (json === false)
            console.log("Requested state file is not found.");
    });
```
 
### Success Response
 
If the result is successful, this API can return the following:
 
- The state file was not found.

    ```
    Status Code: 200 OK
    Content: false
    ```
- The state file was deleted successfully.

    ```
    Status Code: 200 OK
    Content: true
    ```
 
## Copy and Clone a State File
  
### Request Payload
 
To copy state files, you need to pass the following parameters in the request body:
 
- **UserId**=[string] - an identifier of the user whose file you want to copy.
- **StateId**=[string] - an identifier of the state file you want to copy.
- **Overwrite**=[boolean] - allows for overwriting state files.

```
const parameters = {
    "CopyFrom": {
        "UserId": "sourceUserId",
        "StateId": "sourceStateId"
    },
    "Overwrite": true
};
```
 
Note that **userId** and **stateId** in the request URL are the destination identifiers.
 
### Request Example
 
```
const userId = "JohnWood";
const stateId = "Invitation";
const sourceUserId = "masteruser";
const sourceStateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
const parameters = {
    "CopyFrom": {
        "UserId": sourceUserId,
        "StateId": sourceStateId
    },
    "Overwrite": true
};
fetch(url, {
        method: "POST",
        headers: {
            "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
            "Accept": "application/json",
            "Content-Type": "application/json"
        },
        body: JSON.stringify(parameters)
    })
    .then(
        response => {
            if (response.ok)
                console.log("The state file was copied.");
            else
                console.log("Failed to copy the state file.");
        }
    );
```
 
### Success Response
 
When a state file has been successfully copied, this controller returns:

```
Status Code: 204 No Content
```
 
## Modify a State File
  
The **StateFiles** controller allows you to modify state files. Depending on the **type** parameter, you can either update images obtained from external sources through direct URLs, replace Depositphotos previews with purchased images, specify product tags, or save personalization data.
 
### Request Payload
 
This PATCH request expects the **type** parameter in the request body. You can define one of the following values:
 
- **MemorySourceReloadAll** reloads all images in a state file.
- **PatchImageItems** replaces Depositphotos previews with purchased images. This type additionally requires links to the purchased images. For an example, refer to the [Depositphotos Assets](https://customerscanvas.com/docs/cc6/depositphotos-assets.htm.md) topic.
- **PatchProductTags** defines [product tags](https://customerscanvas.com/docs/cc6/product-tags.htm.md). This type requires a JSON structure or an array. After you have defined new tags for a product, old tags are discarded.
- **VdpData** saves personalization data. This type additionally takes [dataSet](https://customerscanvas.com/docs/cc6/web-api-for-rendering.htm.md) or [itemsData](https://customerscanvas.com/docs/cc6/web-api-for-rendering.htm.md).
- **Composite** applies several patches to a state file in a single request.

### Example of Reloading Images
 
After your end users have added images through the Asset Manager, the original files may be changed. If the application requires those changes to be applied to saved state files, you can use this Web API method. This method will trigger Customer's Canvas to download new versions of these images and will replace them in the state file. Reloading images invalidates preview and hi-res links in the cache, thus they are recreated based on the new versions of these images when the application requests them next time.
 
If the original image has been edited so that its dimensions have changed, then the new image is arbitrarily resized to fit into the old bounds when reloading this image. If any of the original images are deleted, the controller returns the 500 Server error and does not reload images.
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
fetch(url, {
        method: "PATCH",
        headers: {
            "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
            "Content-Type": "application/json"
        },
        body: JSON.stringify({
            type: "MemorySourceReloadAll"
        })
    })
    .then(
        response => {
            if (response.ok)
                console.log("Images were reloaded successfully.");
            else
                console.log("Failed to reload images.");
        }
    );
```
 
### Example of Specifying Product Tags
 
You can set product tags as follows:
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
const data = {"product": "postcard", "design": "flowers", "colorTheme": "red"};

fetch(url, {
    method: "PATCH",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
        "Content-Type": "application/json"
    },
    body: JSON.stringify({
        type: "PatchProductTags",
        data: data
    })
});
```
 
You may want to save variable data in product tags to implement personalized rendering. In this case, you can organize them in an array so that each element represents a data set to render an output image. The data set, in turn, is an array of objects defining how a single field should appear in the hi-res output. For example, you can define the **data** to render two product copies with predefined values of the **Name**, **Photo**, and **Barcode** elements as follows:
 
```
const data = [
    [
        { name: "Name", value: "Neo", type: "InString" },
        { name: "Photo", value: "https://example.com/Neo.jpg", type: "ImagePlaceholder" },
        { name: "Barcode", value: "1234567", type: "BarcodePlaceholder", barcodeFormat: "EAN-8" }
    ],
    [
        { name: "Name", value: "Trinity", type: "InString" },
        { name: "Photo", value: "https://example.com/Trinity.jpg", type: "ImagePlaceholder" },
        { name: "Barcode", value: "7654321", type: "BarcodePlaceholder", barcodeFormat: "EAN-8" }
    ]
];
```
 
Such an object may define the following properties:
 
- **name**: string - the element name on the canvas.
- **value**: string - either text or link to an iamge.
- **type**: string - the design element type, one of **"Image"** | **"ImagePlaceholder"** | **"Text"** | **"InString"** | **"BarcodePlaceholder"**.
- **barcodeFormat**: string - the applicable barcode format, one of **"EAN-8"** | **"EAN-13"** | **"QR-CODE"**.
- **barcodeSubType**: string - the barcode sub type, one of **"Phone"** | **"Url"** | **"None"**.

You can also refer to the following example to find out how to save the personalization data through the **VdpData** request.
 
### Example of Saving Personalization Data
 
The following example illustrates how you can save **itemsData** to a state file.
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
const parameters = {
    "type": "VdpData",
    "itemsData": {
        "Name": {
            text: "Christopher",
            font: { fauxItalic: true }
        }
    }
};

fetch(url, {
    method: "PATCH",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
        "Content-Type": "application/json"
    },
    body: JSON.stringify(parameters)
});
```
 
### Example of a Composite Request
 
In the request body, you must pass **commands** - an array with the parameters of the required patches.
 
The following example illustrates how you can both personalize a state file and specify product tags in a **composite** request.
 
```
const userId = "JohnWood";
const stateId = "c9846515-98ce-4f5a-b0b7-f585be3faf3f";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}`;
const parameters = {
    "type": "Composite",
    "commands": [
        {
            "type": "VdpData",
            "dataSet": {
                "surfacesData": [
                    {
                        "surfaceBinding": {
                            "surfaceIndexes": [ 0 ]
                        },
                        "data": [
                            {
                                "Name": { "text": "John Wood" }
                            },
                            {
                                "Name": { "text": "Cristopher Bennet" }
                            }
                        ]
                    }
                ]
            },
            "itemsData": null
        },
        {
            "type": "PatchProductTags",
            "data": { "product": "invitation", "design": "BBQ" }
        }
    ]
};

fetch(url, {
    method: "PATCH",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
        "Content-Type": "application/json"
    },
    body: JSON.stringify(parameters)
});
```
 
### Success Response
 
When a state file has been successfully patched, this controller returns:

```
Status Code: 204 No Content
```
 
## Get Product Tags from a State File
  
To retrieve product tags, you can make the following request.
 
### Request Example
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}/tags`;

console.log(await (await fetch(url, {
    method: "GET",
    headers: {
        "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
        "Content-Type": "application/json"
    }
}).json));
```
 
### Success Response
 
For example, you can get the following response.

```
Status Code: 200 OK
Content:
{ "product": "postcard", "design": "flowers", "colorTheme": "red" }
```
 
## Get Variable Items from a State File
  
To retrieve variable items, you can make the following request.
 
### Request Example
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}/variables`;

(async() => {
    const response = await fetch(url, {
        method: "GET",
        headers: {
            "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
            "Content-Type": "application/json"
        }
    });

    console.log(await response.json());
})()    
```
 
### Success Response
 
For example, you can get the following response if a product contains three variable items: a text, an in-string placeholder, and an image.

```
Status Code: 200 OK
Content:
[
  { "name": "Sale", "value": "BBQ burger", "type": "Text" },
  { "name": "Promo", "value": "2 For $5.99 Each", "type": "InString" },
  { "name": "Photo", "value": null, "type": "Image" }
]
```
 
## Get the Entire Object Model from a State File
  
To retrieve a list of design items, you can make the following request.
 
### Request Example
 
```
const userId = "JohnWood";
const stateId = "1f190673-226d-4c31-87b4-0140805cc445";
const url = `https://localhost:44300/api/users/${userId}/states/${stateId}/model`;

(async () => {
    const response = await fetch(url, {
        method: "GET",
        headers: {
            "X-CustomersCanvasAPIKey": "UniqueSecurityKey",
            "Content-Type": "application/json"
        }
    });
    const model = await response.json();
    if (response.status === 200) {
        // Output the object model.
        console.log(model);
        // Output the name and type of design items on the first page.
        model.surfaces[0].containers.find(c => c.name === "Main").items.forEach(item => {
            console.log("Name: " + item.name, " Type: " + item.$type);
        });
    }
    else if (response.status === 500)
        // Exception details.
        console.log(result.details);
})()
```
 
If the state file contains only two items, this example may return the following list.

```
Name: design.pdf  Type: ImageItem
Name: caption  Type: PlainTextItem
```
 
### Success Response

```
Status Code: 200 OK
Content:
{
    defaultCropMarks: null,
    defaultDesignLocation: {isEmpty: true, x: 0, y: 0},
    defaultSafetyLines: null,
    id: "c1295e78-c3a1-47d0-b80c-d870d1f0e69f",
    name: null,
    surfaces: [
        {width: 161.517532, height: 161.517532, rotateAngle: 0, tags: {...}, size: "161.517532, 161.517532", ...}
    ],
    tags: {printColorSpace: "Rgb", userId: "default"},
    version: "5.32.100",
    watermarkConfig: {text: {...}, image: null, visibility: {...}}
}
```
 
## See Also
  
### Manual
 
- [Web API](https://customerscanvas.com/docs/cc6/webapi.htm.md)
- [Creating and Editing Templates in Customer's Canvas](https://customerscanvas.com/docs/cc6/creating-templates-without-Photoshop.htm.md)
- [Depositphotos Assets](https://customerscanvas.com/docs/cc6/depositphotos-assets.htm.md)

### Downloads
 
- [Code sample](https://customerscanvas.com/docs/cc6/samples/StateFilesAPI.zip)
