From canva-pack
Diagnoses Canva Connect API errors like 401, 403, 429 with payloads, causes, TypeScript fixes, OAuth refresh, and rate limits. For debugging integrations.
How this skill is triggered — by the user, by Claude, or both
Slash command
/canva-pack:canva-common-errorsThis skill is limited to the following tools:
The summary Claude sees in its skill listing — used to decide when to auto-load this skill
Quick reference for the most common Canva Connect API errors at `api.canva.com/rest/v1/*` with real HTTP status codes, error payloads, and fixes.
Quick reference for the most common Canva Connect API errors at api.canva.com/rest/v1/* with real HTTP status codes, error payloads, and fixes.
{ "error": "invalid_token", "message": "The access token is invalid or expired" }
Cause: Access tokens expire after ~4 hours. Token may be malformed or revoked.
Fix:
// Refresh the token
const res = await fetch('https://api.canva.com/rest/v1/oauth/token', {
method: 'POST',
headers: {
'Authorization': `Basic ${Buffer.from(`${clientId}:${clientSecret}`).toString('base64')}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token: storedRefreshToken,
}),
});
const { access_token, refresh_token } = await res.json();
// IMPORTANT: Each refresh token is single-use — store the new one
{ "error": "insufficient_scope", "message": "Required scope: design:content:write" }
Cause: Your integration doesn't have the required OAuth scope enabled, or the user isn't authorized for the resource.
Fix:
{ "error": "rate_limit_exceeded", "message": "Rate limit exceeded" }
Cause: Exceeded per-endpoint rate limits. Key limits:
| Endpoint | Limit |
|---|---|
GET /v1/users/me | 10 req/min |
POST /v1/designs | 20 req/min |
GET /v1/designs | 100 req/min |
POST /v1/exports | 75 req/5min, 500/24hr (per user) |
POST /v1/asset-uploads | 30 req/min |
POST /v1/autofills | 60 req/min |
POST /v1/folders | 20 req/min |
Fix:
async function canvaAPIWithRetry(path: string, token: string, opts: RequestInit = {}) {
const res = await fetch(`https://api.canva.com/rest/v1${path}`, {
...opts,
headers: { 'Authorization': `Bearer ${token}`, 'Content-Type': 'application/json', ...opts.headers },
});
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get('Retry-After') || '60');
console.warn(`Rate limited — waiting ${retryAfter}s`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
return canvaAPIWithRetry(path, token, opts); // Retry once
}
if (!res.ok) throw new Error(`Canva ${res.status}: ${await res.text()}`);
return res.json();
}
Cause: Design, asset, template, or folder ID doesn't exist, was deleted, or the user doesn't have access.
Fix:
# Verify the resource exists — check design ID
curl -s -H "Authorization: Bearer $TOKEN" \
https://api.canva.com/rest/v1/designs/$DESIGN_ID | jq '.design.id'
Common cases:
{ "error": "validation_error", "message": "Design title invalid" }
| Field | Constraint |
|---|---|
title | 1-255 characters |
design_type.width | 40-8000 pixels |
design_type.height | 40-8000 pixels |
format.quality (JPG) | 1-100 |
format.width/height (export) | 40-25000 pixels |
| Chart data | Max 100 rows, 20 columns |
| Code | Meaning | Solution |
|---|---|---|
license_required | Design uses premium elements | User needs Canva Pro subscription |
approval_required | Design pending approval | User must approve in Canva |
internal_failure | Canva server error | Retry after delay |
| Code | Meaning | Solution |
|---|---|---|
invalid_client | Wrong client_id or secret | Check credentials |
invalid_grant | Auth code expired/reused | Restart OAuth flow |
invalid_scope | Scope not enabled | Enable in integration settings |
unsupported_grant_type | Wrong grant_type | Use authorization_code or refresh_token |
# Check your token
curl -s -H "Authorization: Bearer $TOKEN" \
https://api.canva.com/rest/v1/users/me | jq
# Check API connectivity
curl -sI https://api.canva.com/rest/v1/users/me \
-H "Authorization: Bearer $TOKEN" 2>&1 | head -5
# Verify environment variables
echo "Client ID: ${CANVA_CLIENT_ID:+[SET]}"
echo "Access Token: ${CANVA_ACCESS_TOKEN:+[SET]}"
| Error | Cause | Solution |
|---|---|---|
ENOTFOUND | DNS failure | Check network connectivity |
ETIMEDOUT | Network timeout | Increase timeout, check firewall |
invalid_token | Expired access token | Refresh via OAuth endpoint |
insufficient_scope | Missing permission | Enable scope, re-authorize |
For comprehensive debugging, see canva-debug-bundle.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin canva-packIdentifies Canva Connect API pitfalls like token expiry, refresh token reuse, sync export polling, and rate limits. Use for reviewing code, onboarding, or auditing integrations.
Creates, edits, and optimizes skills for Claude Code, including drafting, evaluating with test prompts, iterating on performance, and improving skill descriptions for better triggering accuracy.