Publish extensions

What are publish extensions? Why create one?

A publish extension adds a publish destination to Canva. This destination appears in the Publish menu. Users can then publish their designs to the destination platform.

These are some examples of apps with publish extensions:

  • Pinterest - Post designs to your boards on Pinterest.
  • Slack - Share designs to your channels on Slack.
  • Twitter - Post designs on Twitter.

You can find more examples at

A publish extension can publish the user's design in any of the following formats:

  • JPG
  • PNG
  • PDF
  • PPTX

You can configure the supported formats via the Developer Portal.

Users can find publish extensions via the Publish menu.

When a user opens a publish extension, the user experience depends on the layout of the extension, which you can configure via the Developer Portal. This is an example of the user experience of an extension that uses the Basic layout:

When a user clicks the Save button, Canva sends a request to the destination platform to upload the user's design. The extension then responds with a URL where the user can view their design on the destination platform.

With additional configuration, a publish extension can also:

At its most basic, a publish extension is a REST API.

Canva expects this API to have the following endpoints:

As a user interacts with a publish extension via Canva's UI, Canva sends requests to these endpoints and expects to receive responses in a format that it understands.

The request-response cycle of a publish extension depends on the extension's layout. This is the request-response cycle of a publish extension that uses the Basic layout:

  • Publish extensions can't publish designs as videos, GIFs, or HTML. Some apps, like the Twitter app, can publish videos because they're created by Canva.
  • You're not allowed to create publish extensions that let users print their designs on physical products.
const express = require("express");
const jimp = require("jimp");
const path = require("path");
const url = require("url");
const app = express();
app.use(express.static("public"));"/publish/resources/upload", async (request, response) => {
// Download the image
const [asset] = request.body.assets;
const image = await;
// Write the file to disk
const filePath = path.join(__dirname, "public",;
await image.writeAsync(filePath);
// Respond to the request
type: "SUCCESS",
url: url.format({
protocol: request.protocol,
host: request.get("host"),
app.listen(process.env.PORT || 3000);