Agent skill
canva
Canva API for design creation. Use when user mentions "Canva", "create design", "Canva template", or asks about design graphics.
Install this agent skill to your Project
npx add-skill https://github.com/vm0-ai/vm0-skills/tree/main/canva
SKILL.md
Canva API
Use the Canva Connect API via direct curl calls to manage designs, folders, assets, and comments.
Official docs:
https://www.canva.dev/docs/connect/
When to Use
Use this skill when you need to:
- List and search designs in a Canva account
- Create new designs (documents, presentations, whiteboards, or custom sizes)
- Export designs as PDF, PNG, JPG, or other formats
- Upload assets (images, videos) to Canva
- Manage folders and organize designs
- Add comments to designs for collaboration
- Get user profile information
Prerequisites
Rate Limits
Canva API has per-user rate limits that vary by endpoint. Most read endpoints allow 100 requests/user, write endpoints allow 20-30 requests/user.
How to Use
All examples below assume you have CANVA_TOKEN set.
Base URL: https://api.canva.com/rest/v1
1. Get Current User Profile
Get your user profile information:
curl -s "https://api.canva.com/rest/v1/users/me/profile" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.profile'
2. List Designs
List designs in your account:
curl -s "https://api.canva.com/rest/v1/designs?limit=20" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.items[] | {id, title, created_at, updated_at}'
To search designs by query:
curl -s "https://api.canva.com/rest/v1/designs?query=marketing&limit=10" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.items[] | {id, title}'
Save a design ID from the results for use in subsequent commands.
3. Get Design Details
Get metadata for a specific design. Replace <design-id> with an actual design ID:
curl -s "https://api.canva.com/rest/v1/designs/<design-id>" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.design | {id, title, owner, urls, created_at, updated_at, page_count}'
4. Create a New Design
Create a new document:
Write to /tmp/canva_request.json:
{
"design_type": {
"type": "preset",
"name": "doc"
},
"title": "My New Document"
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/designs" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '.design | {id, title, urls}'
Preset names: doc, presentation, whiteboard
To create a design with custom dimensions (in pixels, 40-8000):
Write to /tmp/canva_request.json:
{
"design_type": {
"type": "custom",
"width": 1080,
"height": 1080
},
"title": "Instagram Post"
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/designs" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '.design | {id, title, urls}'
5. Export Design as PDF
Export a design as PDF. Replace <design-id> with an actual design ID:
Write to /tmp/canva_request.json:
{
"design_id": "<design-id>",
"format": {
"type": "pdf",
"size": "a4"
}
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/exports" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '{id: .job.id, status: .job.status}'
Then poll for completion. Replace <export-id> with the job ID from above:
curl -s "https://api.canva.com/rest/v1/exports/<export-id>" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '{status: .job.status, urls: .job.urls}'
When status is success, download URLs are valid for 24 hours.
6. Export Design as PNG
Export a design as PNG. Replace <design-id> with an actual design ID:
Write to /tmp/canva_request.json:
{
"design_id": "<design-id>",
"format": {
"type": "png",
"width": 1024,
"transparent_background": true
}
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/exports" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '{id: .job.id, status: .job.status}'
Poll with the same export status endpoint as above.
7. List Design Pages
Get all pages of a design. Replace <design-id> with an actual design ID:
curl -s "https://api.canva.com/rest/v1/designs/<design-id>/pages" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.items[] | {index: .index, title: .title, width: .width, height: .height}'
8. Create a Folder
Create a new folder to organize designs:
Write to /tmp/canva_request.json:
{
"name": "Marketing Assets",
"parent_folder_id": "root"
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/folders" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '.folder | {id, name}'
9. List Folder Items
List items in a folder. Replace <folder-id> with an actual folder ID:
curl -s "https://api.canva.com/rest/v1/folders/<folder-id>/items?limit=20" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.items[] | {type, id: .design.id // .folder.id, name: .design.title // .folder.name}'
10. Move Item to Folder
Move a design or folder to another folder. Replace <item-id> and <target-folder-id>:
Write to /tmp/canva_request.json:
{
"item_id": "<item-id>",
"to": {
"folder_id": "<target-folder-id>"
}
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/folders/move" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json
11. Get Asset Details
Get metadata for an uploaded asset. Replace <asset-id> with an actual asset ID:
curl -s "https://api.canva.com/rest/v1/assets/<asset-id>" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.asset | {id, name, tags, created_at, updated_at, thumbnail}'
12. Update Asset
Update an asset's name and tags. Replace <asset-id> with an actual asset ID:
Write to /tmp/canva_request.json:
{
"name": "Updated Logo",
"tags": ["logo", "brand", "2025"]
}
Then run:
curl -s -X PATCH "https://api.canva.com/rest/v1/assets/<asset-id>" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '.asset | {id, name, tags}'
13. Delete Asset
Delete an asset (moves to trash). Replace <asset-id> with an actual asset ID:
curl -s -X DELETE "https://api.canva.com/rest/v1/assets/<asset-id>" --header "Authorization: Bearer $(printenv CANVA_TOKEN)"
14. Create Comment Thread
Add a comment to a design. Replace <design-id>:
Write to /tmp/canva_request.json:
{
"message": "Can we adjust the colors here to match the brand guidelines?",
"attached_to": {
"type": "design"
}
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/designs/<design-id>/comments" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '.thread | {id, message}'
15. Reply to Comment Thread
Reply to an existing comment thread. Replace <design-id> and <thread-id>:
Write to /tmp/canva_request.json:
{
"message": "Updated the colors. Please review."
}
Then run:
curl -s -X POST "https://api.canva.com/rest/v1/designs/<design-id>/comments/<thread-id>/replies" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" --header "Content-Type: application/json" -d @/tmp/canva_request.json | jq '.reply | {id, message}'
16. List Brand Templates
List available brand templates (requires Canva Enterprise):
curl -s "https://api.canva.com/rest/v1/brand-templates?limit=20" --header "Authorization: Bearer $(printenv CANVA_TOKEN)" | jq '.items[] | {id, title, created_at}'
Guidelines
- Async jobs: Export, import, upload, autofill, and resize operations are asynchronous. Start the job with POST, then poll the status with GET using the returned job ID until
statusissuccessorfailed. - Pagination: List endpoints return a
continuationtoken. Pass it as a query parameter to get the next page of results. - Design URLs: The
urls.edit_urlandurls.view_urlfields in design responses are valid for 30 days. - Export URLs: Download URLs from export jobs are valid for 24 hours.
- Custom dimensions: Width and height must be between 40 and 8000 pixels.
- Asset uploads: For binary file uploads, use
Content-Type: application/octet-streamwith anAsset-Upload-Metadataheader containing base64-encoded name. - Rate limits: Read endpoints: ~100 req/user. Write endpoints: ~20-30 req/user. Export polling: ~120 req/user.
Didn't find tool you were looking for?