Migration guide
This guide explains all of the code changes required to upgrade to Apps SDK v2. For general information about migration, including deadlines, see the Migration FAQ.
Packages
All the npm packages for the Apps SDK have been updated with new TypeScript definitions. These definitions make it easier to identify what parts of your codebase need to be updated.
To install the updates, run the following command:
npm install @canva/asset@latest @canva/design@latest @canva/error@latest @canva/platform@latest @canva/user@latest
AI disclosure
In v2, an aiDisclosure
property is required when uploading assets. This property indicates whether an asset was generated by AI, and helps maintain transparency about the origin of assets:
await upload({type: "AUDIO",title: "Example audio",url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",mimeType: "audio/mp3",aiDisclosure: "none", // => Or "app_generated"});
Authentication
In v1, apps could use manual authentication to authenticate users via third-party platforms:
import { auth } from "@canva/user";const response = await auth.requestAuthentication();switch (response.status) {case "COMPLETED":console.log("The authentication was successful.");break;case "ABORTED":console.log("The user exited the authentication flow.");break;case "DENIED":console.log("The user didn't have the required permissions.");break;}
In v2, manual authentication has been deprecated.
Apps have two alternatives for authenticating users:
Feature support
Apps can now run in documents, but some APIs aren't compatible with documents.
In v1, there's no workaround for this. If an app uses incompatible APIs, it will be disabled for documents.
In v2, we've introduced the following methods:
isSupported
registerOnSupportChange
Apps can use these methods to check if a method is available in the current context. This allows the app to adapt to the context in which it's running.
For example, the following Add element at point button will be disabled if the app is running in a document, since the addElementAtPoint
method (also introduced in v2) is not compatible with documents:
import { Button, Rows } from "@canva/app-ui-kit";import { addElementAtCursor, addElementAtPoint } from "@canva/design";import { useFeatureSupport } from "utils/use_feature_support"; // https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/utils/use_feature_support.tsimport * as styles from "styles/components.css";export const App = () => {const isSupported = useFeatureSupport();function handleAddElementAtPoint() {if (!isSupported(addElementAtPoint)) {return;}addElementAtPoint({type: "text",children: ["Hello world"],});}function handleAddElementAtCursor() {if (!isSupported(addElementAtCursor)) {return;}addElementAtCursor({type: "text",children: ["Hello world"],});}return (<div className={styles.scrollContainer}><Rows spacing="1u"><Buttonvariant="primary"onClick={handleAddElementAtPoint}disabled={!isSupported(addElementAtPoint)}>Add element at point</Button><Buttonvariant="primary"onClick={handleAddElementAtCursor}disabled={!isSupported(addElementAtCursor)}>Add element at cursor</Button></Rows></div>);};
To learn more, see Feature support.
Adding elements
In v1, elements could be added to a design with the addNativeElement
method:
await addNativeElement({type: "TEXT",children: ["Hello world"],});
In v2, this method has been deprecated and superseded by the following methods:
addElementAtPoint
, which is a renamed version ofaddNativeElement
.addElementAtCursor
, which is a new method that's compatible with documents.
These methods are only available in certain contexts and, as a result, apps should use the isSupported
method to check that the methods are available in the current context before calling them:
import { Button, Rows } from "@canva/app-ui-kit";import { addElementAtCursor, addElementAtPoint } from "@canva/design";import { useFeatureSupport } from "utils/use_feature_support"; // https://github.com/canva-sdks/canva-apps-sdk-starter-kit/blob/main/utils/use_feature_support.tsimport * as styles from "styles/components.css";export const App = () => {const isSupported = useFeatureSupport();function handleAddElementAtPoint() {if (!isSupported(addElementAtPoint)) {return;}addElementAtPoint({type: "text",children: ["Hello world"],});}function handleAddElementAtCursor() {if (!isSupported(addElementAtCursor)) {return;}addElementAtCursor({type: "text",children: ["Hello world"],});}return (<div className={styles.scrollContainer}><Rows spacing="1u"><Buttonvariant="primary"onClick={handleAddElementAtPoint}disabled={!isSupported(addElementAtPoint)}>Add element at point</Button><Buttonvariant="primary"onClick={handleAddElementAtCursor}disabled={!isSupported(addElementAtCursor)}>Add element at cursor</Button></Rows></div>);};
To learn more, see:
Asset IDs
In v1, the upload
method accepted an id
property:
await upload({type: "IMAGE",id: "exampleid",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"});
This property has been deprecated for a while and, in v2, it's been removed entirely:
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",});
Audio asset duration
In v1, the upload
method accepted a durationMs
property for audio assets:
await upload({type: "AUDIO",title: "Example audio",url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",mimeType: "audio/mp3",durationMs: 86047,aiDisclosure: "none",});
In v2, this property has been deprecated and should not be used:
await upload({type: "AUDIO",title: "Example audio",url: "https://www.canva.dev/example-assets/audio-import/audio.mp3",mimeType: "audio/mp3",aiDisclosure: "none",});
Discriminators
In v1, some discrimintor values were uppercase:
await addNativeElement({type: "EMBED",url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",});
In v2, all discriminator values are lowercase:
await addNativeElement({type: "embed",url: "https://www.youtube.com/watch?v=dQw4w9WgXcQ",});
Drag and drop
In v1, apps could support drag and drop with the startDrag
or makeDraggable
methods:
ui.startDrag(event, {type: "TEXT",children: ["Add text into a design"],});
ui.makeDraggable({node,dragData: {type: "TEXT",children: ["Hello world"],},onDragStart: () => {console.log("The drag event has started");},onDragEnd: () => {console.log("The drag event has ended");},});
In v2, startDrag
has been deprecated and makeDraggable
has been removed.
Instead, apps should use the following methods:
startDragToPoint
startDragToCursor
startDragToPoint
is identical to startDrag
, aside from the name, while startDragToCursor
is a new method that's compatible with documents.
Because these methods are only available in certain contexts, apps should use the isSupported
method to check that the methods are available in the current context.
To learn more, see:
Uploading assets
In v1, the queueMediaUpload
and whenUploaded
methods preceded the upload
method. These methods have been deprecated for a while and have now been removed.
Apps should only upload assets with the upload
method.