Free tools Windows power users keep installed

One-click scans. No signup required.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Some links on this page are affiliate links: if you buy through them we may earn a commission, at no extra cost to you.

Use Canva’s REST API in one of two ways: call POST /rest/v1/designs when you need a new canvas, or call POST /rest/v1/autofills when you need to populate a reusable template with data. Direct design creation returns a design immediately; Autofill is an asynchronous job that you submit, persist, poll, and then hand off through the returned Canva design URL.

The examples below show OAuth bearer-token requests, dataset discovery, polling, validation, rate-limit handling, and the limits that matter in production. They use placeholders for your token, template ID, design ID, and field names because those values belong to your Canva account.

Choose the Canva API path that matches your job

Requirement Use Create design Use Autofill
Starting point A new blank, preset, custom, copied, or (currently preview) brand-template design An existing brand template or design with autofillable fields
Input Canvas settings and optional asset Structured data mapped to fields discovered from the current dataset
Execution Synchronous design creation Asynchronous job submission and polling
Editable result An asset supplied at creation is placed as one flat image Template elements remain editable in Canva
Important limit 20 requests per minute per user; custom dimensions are 40–8,000 pixels per side and 25,000,000 pixels maximum area 60 submissions and 120 job-retrieval requests per minute per user

When direct creation is the right fit

Choose Create design when your application is making a new canvas and can supply the content or an asset separately. The endpoint accepts preset design types, custom dimensions, a copy of an existing design, and creation from a brand template (the latter is currently preview). If you pass an image at creation time, Canva places it as a single flat image. Use Canva’s image-to-design import workflow instead when you need separate editable layers.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

When Autofill is the right fit

Choose Autofill when a designer has prepared a reusable brand template or a design containing tagged fields. Your code supplies text, media, charts, or sheets for those fields, and Canva creates a personalized design. The field names and data types are account-specific and can change, so query the dataset immediately before each generation run.

Access, OAuth, and account prerequisites

Every request acts on behalf of a Canva user. Build an OAuth flow, store access and refresh credentials securely, and handle token expiry rather than embedding a long-lived token in source code. Canva’s guide requires multifactor authentication on the account and a plan that includes Autofill, such as Canva Pro (including Canva Education and Canva for Nonprofits), Canva Teams, or Canva Enterprise.

Request only the scopes your integration needs. Creating an Autofill job requires design:content:write. Retrieving an Autofill job requires design:meta:read. Use the same least-privilege approach for direct design creation and any subsequent folder or export operations, following Canva’s current authorization requirements.

Create a new design with REST

Minimal preset request

Send a bearer token and JSON body to https://api.canva.com/rest/v1/designs. This example requests a document preset:

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.
curl -X POST "https://api.canva.com/rest/v1/designs" 
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" 
  -H "Content-Type: application/json" 
  -d '{
    "type": "type_and_asset",
    "design_type": {"type": "preset", "name": "doc"},
    "title": "My design"
  }'

Keep the response body and the design identifier. Your application can then add content through the appropriate Canva APIs or direct the user to the design for editing.

Custom dimensions and other creation modes

For a custom canvas, provide width and height in pixels. Each side must be between 40 and 8,000 pixels, and width multiplied by height cannot exceed 25,000,000 pixels squared. The same endpoint also supports copying an existing design and (currently preview) creating from a brand template; use the exact request shape documented for the mode you select.

Python

import requests

TOKEN = "YOUR_ACCESS_TOKEN"
payload = {
    "type": "type_and_asset",
    "design_type": {"type": "preset", "name": "doc"},
    "title": "My design",
}
r = requests.post(
    "https://api.canva.com/rest/v1/designs",
    headers={
        "Authorization": f"Bearer {TOKEN}",
        "Content-Type": "application/json",
    },
    json=payload,
    timeout=30,
)
r.raise_for_status()
print(r.json())

Node.js

const token = process.env.CANVA_ACCESS_TOKEN;
const res = await fetch('https://api.canva.com/rest/v1/designs', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({
    type: 'type_and_asset',
    design_type: { type: 'preset', name: 'doc' },
    title: 'My design'
  })
});
if (!res.ok) throw new Error(`${res.status}: ${await res.text()}`);
console.log(await res.json());

Generate a personalized design with Autofill

Autofill is a workflow, not a single fire-and-forget request. Implement these steps in order:

  1. Prepare the source. Create a brand template or design and tag the fields that users may personalize.
  2. Read the dataset. Call the dataset endpoint for the source, such as GET /brand-templates/{TEMPLATE-ID}/dataset, or the corresponding design dataset endpoint. Record each field’s current name and type.
  3. Validate locally. Check that required values are present and that text, image/video media, chart, and sheet values match the types returned by the dataset.
  4. Submit a job. POST to https://api.canva.com/rest/v1/autofills with type set to create_from_brand_template, create_from_design, or update_design, plus the source identifier and data object required by the current API schema.
  5. Persist the job ID. Store it with your input, user, and retry state before polling.
  6. Poll. GET /rest/v1/autofills/{jobId} until the status is success or failed.
  7. Complete the handoff. On success, use the returned Canva design URL and thumbnail. The official guide’s flow sends the user to that URL so they can open the editor, adjust the result, and export it.

Submit an Autofill job with cURL

curl -X POST "https://api.canva.com/rest/v1/autofills" 
  -H "Authorization: Bearer YOUR_ACCESS_TOKEN" 
  -H "Content-Type: application/json" 
  -d '{
    "type": "create_from_brand_template",
    "brand_template_id": "YOUR_TEMPLATE_ID",
    "data": {
      "headline": {"type": "text", "text": "Launch day"},
      "hero_image": {"type": "image", "asset_id": "YOUR_ASSET_ID"}
    }
  }'

The field keys and value objects in this example are illustrative. Replace them with the names and data shapes returned by your dataset response; do not hard-code a template schema that your application has not just queried.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Python submission and bounded polling

import time
import requests

TOKEN = "YOUR_ACCESS_TOKEN"
headers = {
    "Authorization": f"Bearer {TOKEN}",
    "Content-Type": "application/json",
}
base = "https://api.canva.com/rest/v1"

# Discover the current schema first.
dataset = requests.get(
    f"{base}/brand-templates/YOUR_TEMPLATE_ID/dataset",
    headers=headers,
    timeout=30,
)
dataset.raise_for_status()
print("Current fields:", dataset.json())

payload = {
    "type": "create_from_brand_template",
    "brand_template_id": "YOUR_TEMPLATE_ID",
    "data": {
        "headline": {"type": "text", "text": "Launch day"}
    },
}
job = requests.post(
    f"{base}/autofills", headers=headers, json=payload, timeout=30
)
job.raise_for_status()
job_id = job.json()["id"]

for attempt in range(10):
    status = requests.get(
        f"{base}/autofills/{job_id}", headers=headers, timeout=30
    )
    status.raise_for_status()
    result = status.json()
    state = result.get("status")
    if state in ("success", "failed"):
        print(result)
        break
    time.sleep(min(2 ** attempt, 30))
else:
    raise TimeoutError("Autofill job did not finish within the polling window")

Node.js submission and polling

const token = process.env.CANVA_ACCESS_TOKEN;
const headers = {
  'Authorization': `Bearer ${token}`,
  'Content-Type': 'application/json'
};
const base = 'https://api.canva.com/rest/v1';

const submit = await fetch(`${base}/autofills`, {
  method: 'POST',
  headers,
  body: JSON.stringify({
    type: 'create_from_brand_template',
    brand_template_id: 'YOUR_TEMPLATE_ID',
    data: { headline: { type: 'text', text: 'Launch day' } }
  })
});
if (!submit.ok) throw new Error(`${submit.status}: ${await submit.text()}`);
const { id } = await submit.json();

for (let attempt = 0; attempt < 10; attempt++) {
  const check = await fetch(`${base}/autofills/${id}`, { headers });
  if (!check.ok) throw new Error(`${check.status}: ${await check.text()}`);
  const result = await check.json();
  if (result.status === 'success' || result.status === 'failed') {
    console.log(result);
    break;
  }
  await new Promise(r => setTimeout(r, Math.min(2 ** attempt * 1000, 30000)));
}

Handle schema changes and skipped fields

Canva may rename or remove fields. If a submitted field name no longer exists, Canva silently skips it rather than necessarily failing the entire job. Query the dataset immediately before submission, compare it with the values you plan to send, and make missing required fields a local validation error. Log the dataset version or field list with each job so an operator can explain why a value did not appear.

Design for rate limits and reliability

Operation Limit Implementation consequence
Create design 20 requests per minute per user Queue bursts and apply per-user throttling
Create Autofill job 60 requests per minute per user Batch work in a queue; do not retry immediately in a tight loop
Get Autofill job 120 requests per minute per user Use increasing poll intervals and stop at a terminal state
  • Persist job IDs before polling so a worker restart does not lose work.
  • Use bounded exponential backoff for transient HTTP errors and rate-limit responses.
  • Cap total polling time and surface a supportable timeout instead of polling forever.
  • Keep submission and polling queues separate; retrieval traffic must not starve new generation requests.
  • Record the Canva user, template or design ID, payload validation result, final status, and returned design URL.

Troubleshooting common failures

401 Unauthorized

The token is missing, expired, malformed, or not sent as Authorization: Bearer .... Refresh the OAuth credential, verify the header, and never put the token in a URL or client-side bundle.

403 Forbidden or plan error

The user may lack the required MFA, an Autofill-enabled Canva plan, or the scope needed for the operation. Confirm account eligibility and request the documented scope during OAuth authorization.

400 validation error

Typical causes are an invalid design type, dimensions outside 40–8,000 pixels, an area above 25,000,000 pixels squared, or data that does not match the dataset type. Print the response body, re-query the dataset, and validate before retrying.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

A field is missing but the job succeeds

Check for a renamed or deleted field. Because unknown field names can be silently skipped, compare the submitted keys with the latest dataset response and alert on any mismatch.

Jobs appear stuck

Make sure your worker is polling the correct job ID and endpoint, uses backoff, and distinguishes nonterminal states from success and failed. After your bounded timeout, retain the job ID for an operator or a later reconciliation pass.

Too many requests

Apply a per-user token bucket, honor server rate-limit responses, and reduce poll frequency. Do not multiply retries across several workers for the same job.

Independent reader supportYour contribution helps us test, update, and keep practical guides available for everyone.Support on Ko-Fi

Or skip the browser setup

If your goal is a clean image of a Canva page or any public web page rather than an editable Canva design, ScreenshotNeo provides a single-call screenshot API. It accepts consent banners before capture and removes more than 60 known consent platforms, newsletter popups, and chat widgets; each cleanup step can be disabled. Bot checks or CAPTCHAs, blank pages, timeouts, failed loads, and cache hits are not billed, and response headers identify the page verdict and whether it was billed. Its MCP server gives Claude, Cursor, and other MCP clients take_screenshot, get_page_info, and capture_pdf tools.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

See the complete parameter list in the ScreenshotNeo API documentation. A one-call capture looks like this:

curl -G "https://api.screenshotneo.com/v1/shot" -d access_key=YOUR_API_KEY --data-urlencode url=https://www.canva.com -o shot.webp

The Free plan includes 1,000 screenshots each month with no card required. Paid plans start at $5 for 3,000 shots, and every feature is available on every plan. Create a free ScreenshotNeo account.

FAQ

Can I update an existing Canva design with Autofill?

Yes. The Autofill operation type includes update_design; use the dataset for that design and submit only fields your integration has validated.

Does successful Autofill automatically download a PNG or PDF?

The documented success response provides a Canva design URL and thumbnail. The supported handoff is to open the design in Canva for adjustment and export; this article does not assume an undocumented automatic-download endpoint.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Can one API request create multiple personalized designs?

Each Autofill submission creates a job. For many recipients, place individual jobs on a queue, enforce the per-user limits, and persist every job ID for reconciliation.

Frequently Asked Questions

Can I update an existing Canva design with Autofill?

Yes. The Autofill operation type includes update_design; use the dataset for that design and submit only fields your integration has validated.

Does successful Autofill automatically download a PNG or PDF?

The documented success response provides a Canva design URL and thumbnail. The supported handoff is to open the design in Canva for adjustment and export; an automatic-download endpoint is not assumed here.

Can one API request create multiple personalized designs?

Each Autofill submission creates a job. For many recipients, queue individual jobs, enforce the per-user limits, and persist every job ID for reconciliation.

Special offer. See more information about Outbyte and uninstall instructions. Please review EULA and Privacy policy.

Product prices and availability are accurate as of the date/time indicated and are subject to change. Any price and availability information displayed on Amazon at the time of purchase will apply.