Containers
When creating a content extension, one of the available options for the Content type field is Containers. If you select this option, the extension can organize content into containers (folders).
If you're looking for the API reference, see /content/resources/find.

Request-response cycle

For the most part, containers work the same way as the other content types. There are, however, a couple of details that affect the request-response cycle:
Canva always requests containers in separate HTTP requests from the other types of content. For example, if you configure a content extension to support images, embeds, and containers, Canva will send one request for the images and embeds, and a different request for the containers.
When a user selects a container, Canva includes a containerId property in both requests. The extension can use this ID to respond with content and sub-containers that belong to the selected container. This is demonstrated in the example.

Notes

  • You can assign thumbnails to containers. This thumbnail should represent or provide an example of the container's contents.

Limitations

  • You can't submit an app for review if it has a content extension that only supports containers. This is because an extension that only supports containers isn't useful.
  • If a content extension supports search, containers appear in search results, but users can't search for content inside specific containers.

Example

This example assumes the extension is configured to support images and containers.
1
const axios = require("axios");
2
const express = require("express");
3
4
const app = express();
5
6
app.use(express.json());
7
app.use(express.static("public"));
8
9
if (!process.env.PIXABAY_API_KEY) {
10
throw new Error("The PIXABAY_API_KEY environment variable is not set");
11
}
12
13
app.post("/content/resources/find", async (request, response) => {
14
// Handle "CONTAINER" requests
15
if (request.body.types.includes("CONTAINER")) {
16
// The user has opened a container
17
if (request.body.containerId) {
18
response.send({
19
type: "SUCCESS",
20
resources: [],
21
});
22
}
23
24
// The user has not opened a container
25
if (!request.body.containerId) {
26
response.send({
27
type: "SUCCESS",
28
resources: [
29
{
30
type: "CONTAINER",
31
id: "animals",
32
name: "Animals",
33
},
34
{
35
type: "CONTAINER",
36
id: "food",
37
name: "Food",
38
},
39
{
40
type: "CONTAINER",
41
id: "people",
42
name: "People",
43
},
44
],
45
});
46
}
47
}
48
49
// Handle "IMAGE" requests
50
if (request.body.types.includes("IMAGE")) {
51
// Configure the request
52
const options = {
53
url: "https://pixabay.com/api/",
54
params: {
55
key: process.env.PIXABAY_API_KEY,
56
},
57
};
58
59
// The user has opened a container
60
if (request.body.containerId) {
61
options.params.category = request.body.containerId;
62
}
63
64
// Send the request
65
const pixabay = await axios.request(options);
66
67
// Transform the array of images into an array of "IMAGE" resources
68
const images = pixabay.data.hits.map((image) => {
69
return {
70
type: "IMAGE",
71
id: image.id,
72
name: `Photo by ${image.user}`,
73
thumbnail: {
74
url: image.webformatURL,
75
height: image.webformatHeight,
76
width: image.webformatWidth,
77
},
78
url: image.webformatURL,
79
contentType: "image/jpeg",
80
};
81
});
82
83
// Provide a success response
84
response.send({
85
type: "SUCCESS",
86
resources: images,
87
});
88
}
89
});
90
91
app.listen(process.env.PORT || 3000);
Copied!
Last modified 27d ago