On September 25th, 2024, we released v2 of the Apps SDK. To learn what’s new and how to upgrade, see Migration FAQ and Migration guide.

Uploading assets

How to upload assets to a user's media library.

Apps can upload assets, such as images or videos, to Canva's backend. The user can access these assets in the Canva editor, via the Uploads tab, and the app can add the assets to the user's design.

Use-cases

These are some examples of apps that can benefit from uploading assets:

The user experience

When an app starts uploading an asset, the user can see the upload progress in the Uploads tab, and the asset's thumbnail is overlaid with a progress indicator. A toast notification appears when the upload is complete.

Upload an asset only with the user's explicit permission and intent, such as when the user clicks a button. It's better to show users a preview of the object to upload first, and then confirm with the user whether to proceed with the upload.

The asset counts against the user's storage quota. If the user has a Canva Pro(opens in a new tab or window) account, their storage quota is 1TB. Otherwise, their storage quota is 5GB.

The uploaded asset is only available to the user who uploaded it.

Supported asset types

Apps can upload the following types of assets to a user's media library:

  • Audio
  • Images
  • Videos

There are limitations that apply to each type of assets, such as supported file formats and sizes.

Audio

Inexact MIME types are allowed for assets that belong to the same format. For example, you can use audio/mpeg for an audio/mp3 file, but audio/wav will not work.

Apps can upload the following types of audio files:

Name
MIME type
Common file extensions
MPEG
audio/mpeg
.mpg, .mpeg, .mp1, .mp2, .mp3
MP4 Audio
audio/mp4
.mp4, .m4a
M4A
audio/x-m4a
.m4a
MP3
audio/mp3
.mp3
OGG
audio/ogg
.ogg, .oga
WAV
audio/wav
.wav
X-WAV
audio/x-wav
.wav
WEBM
audio/webm
.webm

The maximum size of an audio file is 50MB.

Images

The MIME type must match the format of the uploaded asset.

Apps can upload the following types of image files:

Name
MIME type
Common file extensions
HEIC
image/heic
.heic
JPEG
image/jpeg
.jpg, .jpeg
PNG
image/png
.png
SVG
image/svg+xml
.svg
TIFF
image/tiff
.tiff, .tif
WebP
image/webp
.webp

The maximum size of an image file is 50MB, except for SVGs, which are limited to 3MB.

GIFs are handled as videos, not images.

Videos

The MIME type must match the format of the uploaded asset.

Apps can upload the following types of video files:

Name
MIME type
Common file extensions
AVI
video/avi
.avi
GIF
image/gif
.gif
M4V
video/x-m4v
.m4v
Matroska
video/x-matroska
.mkv
QuickTime
video/quicktime
.mov
MP4
video/mp4
.mp4
MPEG
video/mpeg
.mpg, .mpeg
WebM
video/webm
.webm

The maximum size of a video file is 100MB.

How to upload assets

Step 1: Enable the required permissions

To allow the app to upload assets, enable the canva:asset:private:write permission via the Developer Portal. In the future, the Apps SDK will throw an error if the required permissions are not enabled.

To learn more, see Configuring permissions.

Step 2: Start the upload

Import the upload method from the @canva/asset package:

import { upload } from "@canva/asset";
TS

When calling the method, the expected properties depend on the type of asset being uploaded:

The following snippet demonstrates the required properties for uploading audio assets:

const result = await upload({
type: "audio",
title: "Example audio",
mimeType: "audio/mp3",
url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",
aiDisclosure: "none",
});
TS

The following snippet demonstrates the required properties for uploading image assets:

const result = await upload({
type: "image",
mimeType: "image/jpeg",
url: "https://www.canva.dev/example-assets/image-import/image.jpg",
thumbnailUrl:
"https://www.canva.dev/example-assets/image-import/thumbnail.jpg",
aiDisclosure: "none",
});
TS

The following snippet demonstrates the required properties for uploading video assets:

const result = await upload({
type: "video",
mimeType: "video/mp4",
url: "https://www.canva.dev/example-assets/video-import/video.mp4",
thumbnailImageUrl:
"https://www.canva.dev/example-assets/video-import/thumbnail-image.jpg",
thumbnailVideoUrl:
"https://www.canva.dev/example-assets/video-import/thumbnail-video.mp4",
aiDisclosure: "none",
});
TS

In all cases:

  • The URLs must be exposed via the internet and available to Canva's backend. This means localhost URLs won't work.
  • For images and video, the MIME type must match the format of the uploaded asset. However, for audio, inexact MIME types are allowed for assets that belong to the same format. For example, you can use audio/mpeg for an audio/mp3 file, but audio/wav will not work.

If the method call is successful, it returns a reference:

console.log("The reference for the upload is:", result.ref);
TS

A reference is a unique identifier that points to an asset in Canva's backend. This reference lets an app interact with an asset before it has finished uploading.

(Optional) Step 3: Check when the upload is complete

The upload method can return an optional whenUploaded method that informs the user that their upload is complete and returns a Promise. By waiting for the Promise to resolve, the app can determine when an asset has finished uploading:

await result.whenUploaded();
console.log("The upload is complete.");
TS

The whenUploaded method should come after adding the element to the page (such as addElementAtPoint) in your app's code. Doing so retains the upload workflow by placing the thumbnail on the page and prevent a delay in uploading an asset.

(Optional) Step 4: Add the asset to the user's design

By default, uploading an asset only makes it available to a user via their Uploads tab. It doesn't add the asset to the user's design. To learn how to add assets to a design, see:

SVG limitations

This section describes the limitations that apps must consider when uploading SVGs.

File size

For most users, the maximum file size for SVGs is 3MB. If a user is a contributor(opens in a new tab or window), the maximum file size for SVGs is 10MB.

Download timeouts

The SVG image should be downloadable from the server within 5 seconds.

Elements

Some SVG elements (tags) are not allowed and an upload will fail if the elements are present.

Animation elements

  • animate
  • animatemotion
  • animatetransform
  • discard
  • mpath
  • set

Deprecated elements

  • altglyph
  • altglyphdef
  • altglyphitem
  • cursor
  • glyph
  • glyphref
  • missing-glyph
  • tref

Font elements

  • font
  • font-face
  • font-face-format
  • font-face-name
  • font-face-src
  • font-face-uri

Unsafe elements

  • a
  • foreignobject
  • script
  • switch

Attributes

Some attributes are either not allowed in SVG files or have certain restrictions.

Blocked attributes

  • crossorigin
  • lang
  • media
  • onload
  • ping
  • referrerpolicy
  • rel
  • rendering-intent
  • requiredextensions
  • requiredfeatures
  • systemlanguage
  • tabindex
  • transform-origin
  • unicode
  • vector-effect

Restricted attributes

  • The href attribute of an image element only supports data URLs for PNG and JPEG images. Other image formats, such as SVGs, are not supported as data URLs.
  • The URL in a href attribute must not point to a location that exists outside of the SVG.
  • The style attribute must not use the mix-blend-mode property.

Additional considerations

API reference

Code samples

Uploading audio

import React from "react";
import { upload } from "@canva/asset";
export function App() {
async function handleClick() {
// Start uploading the media
const result = await upload({
type: "audio",
title: "Example audio",
mimeType: "audio/mp3",
url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",
aiDisclosure: "none",
});
// Get the reference for the upload
console.log("The reference for the upload is:", result.ref);
// Wait for the upload to complete
await result.whenUploaded();
console.log("The upload is complete.");
}
return (
<div>
<button onClick={handleClick}>Upload audio</button>
</div>
);
}
TSX

Uploading images

import React from "react";
import { upload } from "@canva/asset";
export function App() {
async function handleClick() {
// Start uploading the media
const result = await upload({
type: "image",
mimeType: "image/jpeg",
url: "https://www.canva.dev/example-assets/image-import/image.jpg",
thumbnailUrl:
"https://www.canva.dev/example-assets/image-import/thumbnail.jpg",
aiDisclosure: "none",
});
// Get the reference for the upload
console.log("The reference for the upload is:", result.ref);
// Wait for the upload to complete
await result.whenUploaded();
console.log("The upload is complete.");
}
return (
<div>
<button onClick={handleClick}>Upload image</button>
</div>
);
}
TSX

Uploading videos

import React from "react";
import { upload } from "@canva/asset";
export function App() {
async function handleClick() {
// Start uploading the media
const result = await upload({
type: "video",
mimeType: "video/mp4",
url: "https://www.canva.dev/example-assets/video-import/video.mp4",
thumbnailImageUrl:
"https://www.canva.dev/example-assets/video-import/thumbnail-image.jpg",
thumbnailVideoUrl:
"https://www.canva.dev/example-assets/video-import/thumbnail-video.mp4",
aiDisclosure: "none",
});
// Get the reference for the upload
console.log("The reference for the upload is:", result.ref);
// Wait for the upload to complete
await result.whenUploaded();
console.log("The upload is complete.");
}
return (
<div>
<button onClick={handleClick}>Upload video</button>
</div>
);
}
TSX