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.
npx claudepluginhub jeremylongshore/claude-code-plugins-plus-skills --plugin canva-packThis skill is limited to using the following tools:
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.
Guides Next.js Cache Components and Partial Prerendering (PPR) with cacheComponents enabled. Implements 'use cache', cacheLife(), cacheTag(), revalidateTag(), static/dynamic optimization, and cache debugging.
Guides building MCP servers enabling LLMs to interact with external services via tools. Covers best practices, TypeScript/Node (MCP SDK), Python (FastMCP).
Generates original PNG/PDF visual art via design philosophy manifestos for posters, graphics, and static designs on user request.
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.