# Import a Canva Design

> Turn a public Canva share link into a studio template with one API call. Images are copied to your workspace and fonts matched to your library.

- **URL**: https://orshot.com/docs/api-reference/enterprise-canva-import

---

This endpoint is available as a paid add-on and on the Enterprise plan.
Contact [hi@orshot.com](mailto:hi@orshot.com) to get access.

Import a Canva design into your workspace from its public share link. Orshot reads the design, converts every page to a studio template, copies its images and video clips into your workspace library, and matches its fonts to your uploaded fonts or the closest Google font. The new template is ready to render through the [render API](https://orshot.com/docs/api-reference/render-from-studio-template) right away.

This is the same converter as [importing from Canva in Studio](https://orshot.com/docs/importing-templates/import-from-canva), so a design imports the same way in both places. Use it to move a large Canva library into Orshot, or to import new designs from a recurring job.

By calling this endpoint you confirm that you own the design and its assets, or hold the rights to use them.

## Endpoint

```markdown tab="Endpoint"
https://api.orshot.com/v1/studio/templates/import/canva
```

## Query Parameters

| Parameter           | Type    | Required | Default | Description |
| ------------------- | ------- | -------- | ------- | ----------- |
| `includeThumbnails` | Boolean | No       | `false` | When `true`, a thumbnail for every page is rendered before the response is sent (about 1 to 2 seconds per page). When `false` or absent, thumbnails are generated in the background. |

## Request

**JSON Request**
```js
await fetch("https://api.orshot.com/v1/studio/templates/import/canva", {
  method: "POST",
  headers: {
    "Content-Type": "application/json",
    Authorization: "Bearer <ORSHOT_API_KEY>",
  },
  body: JSON.stringify({
    url: "https://www.canva.com/design/DAGxxxxxxxx/view",
    name: "Open house flyer",
    convertPlaceholders: true,
    tags: ["real-estate", "flyer"],
  }),
});
```

**Response**
```json
{
  "success": true,
  "template": {
    "id": 12345,
    "name": "Open house flyer",
    "pages": 18,
    "canvas_width": 1080,
    "canvas_height": 1350,
    "fonts": {
      "substituted": [
        { "font": "Helvetica World", "usedInstead": "Arimo" },
        { "font": "Proxima Nova", "usedInstead": "Figtree" }
      ],
      "missingStyles": [
        { "font": "Glacial Indifference", "weight": 400, "style": "italic" }
      ]
    },
    "placeholders": ["city_name", "your_name"],
    "modifications": [
      {
        "key": "page1@img_1_2",
        "id": "page1@img_1_2",
        "type": "imageUrl",
        "description": "img_1_2 — Image URL",
        "example": "https://storage.orshot.com/cloud/w-50/brand_assets/1793646784551-imported-template-a4c451c5.png",
        "element_name": "img_1_2",
        "page_number": 1,
        "page_id": "x4w2g34426"
      },
      {
        "key": "page1@text_1_3",
        "id": "page1@text_1_3",
        "type": "text",
        "description": "Text content",
        "example": "Open house in {{city_name}}",
        "page_number": 1,
        "page_id": "x4w2g34426"
      },
      {
        "key": "page1@text_1_3:city_name",
        "id": "page1@text_1_3:city_name",
        "type": "text",
        "description": "Text content",
        "example": "",
        "page_number": 1,
        "page_id": "x4w2g34426"
      }
    ],
    "assets": { "copied": 19, "total": 19, "videos": 0 },
    "tookMs": 4450
  }
}
```

**Dry run response**
```json
{
  "dryRun": true,
  "name": "Things I'm thankful for as a [City Name] real estate agent",
  "pages": 26,
  "canvas_width": 1080,
  "canvas_height": 1350,
  "fonts": {
    "substituted": [
      { "font": "PP Neue Montreal", "usedInstead": "Inter" },
      { "font": "Helvetica World", "usedInstead": "Arimo" }
    ],
    "missingStyles": []
  },
  "placeholders": [],
  "tookMs": 690
}
```

**Error Response**
```json
{
  "error": "Invalid Canva URL format. Please use a public share link from Canva (e.g., https://www.canva.com/design/ABC123/view or https://canva.link/...)",
  "stage": "fetch"
}
```

## Request Body Parameters

| Parameter             | Type    | Required | Description |
| --------------------- | ------- | -------- | ----------- |
| `url`                 | String  | Yes      | Public Canva share link: `https://www.canva.com/design/<id>/view` or a `canva.link` short link. In Canva, open **Share**, set access to **Anyone with the link**, and copy the link. |
| `name`                | String  | No       | Template name, up to 255 characters. Defaults to the design's title in Canva. |
| `convertPlaceholders` | Boolean | No       | When `true`, placeholder text in the design such as `[City Name]`, `{{city_name}}` or `{City Name}` becomes its own parameter (`city_name`), so you can fill just that word when rendering. Default `false`. |
| `tags`                | Array   | No       | Tag strings for the new template, e.g. `["social", "flyer"]`. |
| `dryRun`              | Boolean | No       | When `true`, the design is read and converted but nothing is saved or copied. Use it to check pages, size and font matches before importing. Default `false`. |

## Response Fields

The response is a summary of the new template, not the full design. Fetch the design with [Get Studio Template](https://orshot.com/docs/api-reference/studio-template-get) if you need it.

| Field                     | Type    | Description |
| ------------------------- | ------- | ----------- |
| `template.id`             | Integer | ID of the new studio template. Use it to render. |
| `template.name`           | String  | Template name. |
| `template.pages`          | Integer | Number of pages imported. |
| `template.canvas_width`   | Integer | Canvas width in pixels. |
| `template.canvas_height`  | Integer | Canvas height in pixels. |
| `template.fonts.substituted` | Array | Every font the template draws with a stand-in because it is not in your font library or Google Fonts, each with the font used instead. A font Canva does not name is listed as `Unknown Canva font (<id>)`. An empty list means every text layer uses its original font. [Upload the original fonts](https://orshot.com/docs/api-reference/custom-fonts-post) and import again to use them. |
| `template.fonts.missingStyles` | Array | Weights and italics the design uses in one of your uploaded fonts that Canva has but your upload does not, each as `font`, `weight` and `style`. The template draws them with the closest weight or a slanted copy of the upright. Upload those files under the same family name and import again. Fonts uploaded without a recorded weight are not checked. |
| `template.placeholders`   | Array   | Placeholder names found when `convertPlaceholders` is `true`. |
| `template.modifications`  | Array   | Parameters you can send when rendering. Keys are prefixed with the page (`page1@text_1_3`); a placeholder adds its own key (`page1@text_1_3:city_name`). |
| `template.assets`         | Object  | Images and clips copied from Canva into your workspace: `copied`, `total` and `videos`. |
| `template.thumbnails`     | Object  | Only with `?includeThumbnails=true`: the rendered thumbnail of each page. |
| `template.tookMs`         | Integer | Time the import took, in milliseconds. |

A dry run returns the same summary fields at the top level with `"dryRun": true`, and no `id`, `modifications` or `assets`.

## What is imported

- Every page, at the design's size, with text, shapes, lines, images, frames, grids, gradients and video clips.
- Text keeps its font, size, weight, color, spacing and alignment. Fonts you have uploaded to your workspace are used first, then Google Fonts, then the closest match.
- Images and clips are copied to your workspace, so the template keeps working after the Canva link changes or expires. If any image cannot be copied, nothing is saved and you get a `502` you can retry.
- Every text and image layer becomes a parameter (`text_1_3`, `img_1_2`) you can change when you render. Rename layers in Studio to get readable keys.

Some Canva-only effects may not carry over exactly. Check the template in Studio after importing a new kind of design.

## Errors

| Status | `stage`   | When |
| ------ | --------- | ---- |
| `400`  |           | `url` is missing, or a field has the wrong type. |
| `400`  | `fetch`   | The link is not a Canva design link. |
| `403`  |           | The API key is invalid, or Canva import is not enabled for your workspace. |
| `403`  | `fetch`   | The design is private. Set its share access to **Anyone with the link**. |
| `422`  | `fetch`   | The design is empty or could not be read. |
| `422`  | `convert` | The design could not be converted. |
| `429`  |           | More than 30 requests in a minute, or Canva is limiting reads. Wait and retry; `Retry-After` is set when known. |
| `502`  | `assets`  | Some images could not be copied from Canva. Nothing was saved. Retry. |
| `504`  | `fetch`   | Canva took too long to respond. Retry. |

Errors with `"retryable": true` are safe to retry.

## Rate Limits

| Limit               | Value |
| ------------------- | ----- |
| Requests per minute | 30    |

Designs are read from Canva one at a time, about one every 2 seconds. For a large library, send imports one after another rather than in parallel.