canva-known-pitfalls
Identify and avoid Canva Connect API anti-patterns and common integration mistakes. Use when reviewing Canva code, onboarding developers, or auditing existing Canva integrations for best practices violations. Trigger with phrases like "canva mistakes", "canva anti-patterns", "canva pitfalls", "canva what not to do", "canva code review".
Best use case
canva-known-pitfalls is best used when you need a repeatable AI agent workflow instead of a one-off prompt.
Identify and avoid Canva Connect API anti-patterns and common integration mistakes. Use when reviewing Canva code, onboarding developers, or auditing existing Canva integrations for best practices violations. Trigger with phrases like "canva mistakes", "canva anti-patterns", "canva pitfalls", "canva what not to do", "canva code review".
Teams using canva-known-pitfalls should expect a more consistent output, faster repeated execution, less prompt rewriting.
When to use this skill
- You want a reusable workflow that can be run more than once with consistent structure.
When not to use this skill
- You only need a quick one-off answer and do not need a reusable workflow.
- You cannot install or maintain the underlying files, dependencies, or repository context.
Installation
Claude Code / Cursor / Codex
Manual Installation
- Download SKILL.md from GitHub
- Place it in
.claude/skills/canva-known-pitfalls/SKILL.mdinside your project - Restart your AI agent — it will auto-discover the skill
How canva-known-pitfalls Compares
| Feature / Agent | canva-known-pitfalls | Standard Approach |
|---|---|---|
| Platform Support | Not specified | Limited / Varies |
| Context Awareness | High | Baseline |
| Installation Complexity | Unknown | N/A |
Frequently Asked Questions
What does this skill do?
Identify and avoid Canva Connect API anti-patterns and common integration mistakes. Use when reviewing Canva code, onboarding developers, or auditing existing Canva integrations for best practices violations. Trigger with phrases like "canva mistakes", "canva anti-patterns", "canva pitfalls", "canva what not to do", "canva code review".
Where can I find the source code?
You can find the source code on GitHub using the link provided at the top of the page.
Related Guides
AI Agents for Coding
Browse AI agent skills for coding, debugging, testing, refactoring, code review, and developer workflows across Claude, Cursor, and Codex.
Best AI Skills for Claude
Explore the best AI skills for Claude and Claude Code across coding, research, workflow automation, documentation, and agent operations.
Cursor vs Codex for AI Workflows
Compare Cursor and Codex for AI coding workflows, repository assistance, debugging, refactoring, and reusable developer skills.
SKILL.md Source
# Canva Known Pitfalls
## Overview
Common mistakes when integrating with the Canva Connect API. Each pitfall includes the anti-pattern, why it fails, and the correct approach with real API endpoints.
## Pitfall #1: Not Handling Token Expiry
```typescript
// WRONG — token expires after ~4 hours, then all calls fail
const token = await getTokenOnce();
// ... 5 hours later ...
await canvaAPI('/designs', token); // 401 Unauthorized
// RIGHT — auto-refresh before expiry
class CanvaClient {
async request(path: string, init?: RequestInit) {
if (Date.now() > this.tokens.expiresAt - 300_000) {
await this.refreshToken(); // Refresh 5 min before expiry
}
// ... make request
}
}
```
## Pitfall #2: Reusing Refresh Tokens
```typescript
// WRONG — refresh tokens are single-use in Canva's OAuth
const tokens = await refreshAccessToken(storedRefreshToken);
// Later, using the SAME refresh token again:
const tokens2 = await refreshAccessToken(storedRefreshToken); // FAILS
// RIGHT — always store the new refresh token immediately
const tokens = await refreshAccessToken(storedRefreshToken);
await db.saveTokens(userId, {
accessToken: tokens.access_token,
refreshToken: tokens.refresh_token, // NEW token — store it!
expiresAt: Date.now() + tokens.expires_in * 1000,
});
```
## Pitfall #3: Synchronous Export Polling in Request Handler
```typescript
// WRONG — user waits 5-30 seconds while export completes
app.post('/api/export', async (req, res) => {
const { job } = await canvaAPI('/exports', token, { method: 'POST', body: ... });
while (job.status === 'in_progress') { // Blocks entire request
await sleep(2000);
// ... poll ...
}
res.json({ urls: job.urls }); // User waited 15+ seconds
});
// RIGHT — return job ID, poll asynchronously
app.post('/api/export', async (req, res) => {
const { job } = await canvaAPI('/exports', token, { method: 'POST', body: ... });
res.json({ jobId: job.id, status: 'processing' }); // 200ms response
});
app.get('/api/export/:jobId/status', async (req, res) => {
const { job } = await canvaAPI(`/exports/${req.params.jobId}`, token);
res.json({ status: job.status, urls: job.urls });
});
```
## Pitfall #4: Ignoring Rate Limits
```typescript
// WRONG — blast requests, crash on 429
for (const design of designs) {
await canvaAPI(`/exports`, token, { method: 'POST', body: ... }); // 75/5min limit
}
// RIGHT — queue with rate awareness
import PQueue from 'p-queue';
const queue = new PQueue({ concurrency: 1, interval: 4000, intervalCap: 1 });
for (const design of designs) {
await queue.add(() =>
canvaAPI(`/exports`, token, { method: 'POST', body: ... })
);
}
```
## Pitfall #5: Caching Temporary URLs
```typescript
// WRONG — URLs expire silently
const design = await canvaAPI(`/designs/${id}`, token);
cache.set(id, design, { ttl: 86400 }); // Cache for 24 hours
// But thumbnail URLs expire in 15 minutes!
// RIGHT — cache metadata but refresh URLs
const design = await canvaAPI(`/designs/${id}`, token);
cache.set(`design:meta:${id}`, {
id: design.design.id,
title: design.design.title,
pageCount: design.design.page_count,
// DON'T cache: thumbnail.url (15 min), edit_url (30 days), view_url (30 days)
}, { ttl: 300 }); // 5 min cache
```
## Pitfall #6: Client-Side OAuth
```typescript
// WRONG — client secret exposed in browser
// frontend.js
const tokens = await fetch('https://api.canva.com/rest/v1/oauth/token', {
body: new URLSearchParams({
client_secret: 'EXPOSED_TO_USERS', // Anyone can see this
// ...
}),
});
// RIGHT — token exchange MUST happen server-side
// Canva docs: "Requests that require authenticating with your client ID
// and client secret can't be made from a web-browser client"
```
## Pitfall #7: Not Checking Enterprise Requirements
```typescript
// WRONG — calling autofill without Enterprise, getting 403
const result = await canvaAPI('/autofills', token, { method: 'POST', body: ... });
// 403: "User must be a member of a Canva Enterprise organization"
// RIGHT — check capabilities first
const capabilities = await canvaAPI('/users/me/capabilities', token);
if (!capabilities.capabilities?.includes('autofill')) {
throw new Error('Autofill requires Canva Enterprise subscription');
}
```
## Pitfall #8: Not Validating Webhook Signatures
```typescript
// WRONG — accepts any POST as a valid webhook
app.post('/webhooks/canva', (req, res) => {
processEvent(req.body); // Attacker can send fake events!
res.status(200).send();
});
// RIGHT — verify JWK signature
app.post('/webhooks/canva', express.text({ type: '*/*' }), async (req, res) => {
const payload = await verifyCanvaWebhook(req.body); // JWK verification
if (!payload) return res.status(401).send('Invalid');
res.status(200).send('OK'); // Return 200 first
processEvent(payload).catch(console.error); // Process async
});
```
## Pitfall #9: Ignoring Blank Design Auto-Delete
```typescript
// WRONG — create designs and expect them to persist
const { design } = await canvaAPI('/designs', token, {
method: 'POST',
body: JSON.stringify({ design_type: { type: 'custom', width: 1080, height: 1080 } }),
});
// Design auto-deleted after 7 days if user never edits it!
// RIGHT — warn users or track unedited designs
await notifyUser(`Edit your design before ${sevenDaysFromNow}: ${design.urls.edit_url}`);
```
## Pitfall #10: Not Handling Export Failures
```typescript
// WRONG — assumes exports always succeed
const { job } = await canvaAPI('/exports', token, { method: 'POST', body: ... });
const urls = (await pollExport(job.id)).urls; // Crashes if failed
// RIGHT — handle all export error codes
const result = await pollExport(job.id);
if (result.status === 'failed') {
switch (result.error?.code) {
case 'license_required':
throw new Error('Design uses premium elements — user needs Canva Pro');
case 'approval_required':
throw new Error('Design requires approval before export');
case 'internal_failure':
// Retry after delay
break;
}
}
```
## Quick Reference
| Pitfall | Detection | Prevention |
|---------|-----------|------------|
| Token expiry | 401 errors after 4h | Auto-refresh before expiry |
| Reused refresh token | Token exchange fails | Store new token every refresh |
| Sync export polling | Slow API responses | Return job ID, poll separately |
| Rate limit ignored | 429 errors | Queue with p-queue |
| Cached expired URLs | Broken images/links | Don't cache temp URLs |
| Client-side OAuth | Security audit | Server-side only |
| Missing Enterprise check | 403 on autofill | Check capabilities first |
| Unsigned webhooks | Security audit | JWK verification |
| Blank design deleted | Design disappears | Warn about 7-day window |
| Export error ignored | Crashes | Handle all error codes |
## Resources
- [Canva Authentication](https://www.canva.dev/docs/connect/authentication/)
- [Canva API Reference](https://www.canva.dev/docs/connect/api-reference/)
- [Canva Scopes](https://www.canva.dev/docs/connect/appendix/scopes/)Related Skills
windsurf-known-pitfalls
Identify and avoid Windsurf anti-patterns and common mistakes. Use when onboarding new developers to Windsurf, reviewing AI workflow practices, or auditing Windsurf configuration for issues. Trigger with phrases like "windsurf mistakes", "windsurf anti-patterns", "windsurf pitfalls", "windsurf what not to do", "windsurf gotchas".
vercel-known-pitfalls
Identify and avoid Vercel anti-patterns and common integration mistakes. Use when reviewing Vercel code for issues, onboarding new developers, or auditing existing Vercel deployments for best practice violations. Trigger with phrases like "vercel mistakes", "vercel anti-patterns", "vercel pitfalls", "vercel what not to do", "vercel code review".
supabase-known-pitfalls
Avoid and fix the most common Supabase mistakes: exposing service_role key in client bundles, forgetting to enable RLS, not using connection pooling in serverless, .single() throwing on empty results, missing .select() after insert/update, not destructuring { data, error }, creating multiple client instances, and not using generated types. Use when reviewing Supabase code, onboarding developers, auditing an existing project, or debugging unexpected behavior. Trigger with phrases like "supabase mistakes", "supabase anti-patterns", "supabase pitfalls", "supabase code review", "supabase gotchas", "supabase debugging", "what not to do supabase", "supabase common errors".
snowflake-known-pitfalls
Identify and avoid Snowflake anti-patterns and common mistakes in SQL, warehouse management, data loading, and access control. Use when reviewing Snowflake configurations, onboarding new users, or auditing existing Snowflake deployments for best practices. Trigger with phrases like "snowflake mistakes", "snowflake anti-patterns", "snowflake pitfalls", "snowflake what not to do", "snowflake code review".
shopify-known-pitfalls
Identify and avoid Shopify API anti-patterns: ignoring userErrors, wrong API version, REST instead of GraphQL, missing GDPR webhooks, and webhook timeout issues. Trigger with phrases like "shopify mistakes", "shopify anti-patterns", "shopify pitfalls", "shopify what not to do", "shopify code review".
sentry-known-pitfalls
Identify and fix common Sentry SDK pitfalls that cause silent data loss, cost overruns, and missed alerts. Covers 10 anti-patterns with fix code. Use when auditing Sentry config, debugging missing events, or reviewing SDK setup. Trigger: "sentry pitfalls", "sentry anti-patterns", "sentry mistakes", "why are sentry events missing".
salesforce-known-pitfalls
Identify and avoid Salesforce anti-patterns including SOQL N+1, governor limit violations, and API waste. Use when reviewing Salesforce code for issues, onboarding new developers, or auditing existing Salesforce integrations for best practices violations. Trigger with phrases like "salesforce mistakes", "salesforce anti-patterns", "salesforce pitfalls", "salesforce what not to do", "salesforce code review".
retellai-known-pitfalls
Retell AI known pitfalls — AI voice agent and phone call automation. Use when working with Retell AI for voice agents, phone calls, or telephony. Trigger with phrases like "retell known pitfalls", "retellai-known-pitfalls", "voice agent".
replit-known-pitfalls
Avoid the top Replit anti-patterns: ephemeral filesystem, public secrets, port binding, Nix gotchas, and database limits. Use when reviewing Replit code, onboarding developers, or auditing existing Replit apps for common mistakes. Trigger with phrases like "replit mistakes", "replit anti-patterns", "replit pitfalls", "replit what not to do", "replit code review".
perplexity-known-pitfalls
Identify and avoid Perplexity anti-patterns and common integration mistakes. Use when reviewing Perplexity code, onboarding new developers, or auditing existing integrations for best practices violations. Trigger with phrases like "perplexity mistakes", "perplexity anti-patterns", "perplexity pitfalls", "perplexity code review", "perplexity gotchas".
openrouter-known-pitfalls
Avoid common OpenRouter integration mistakes and gotchas. Use proactively when starting a new integration or reviewing existing code. Triggers: 'openrouter pitfalls', 'openrouter gotchas', 'openrouter mistakes', 'openrouter best practices'.
notion-known-pitfalls
Common Notion API mistakes: wrong page ID format (dashes), rich text array structure, block children not returned with page, pagination required for all lists, 3 req/sec shared across endpoints, not sharing pages with integration. Use when debugging or reviewing Notion code. Trigger with phrases like "notion mistakes", "notion pitfalls", "notion common errors", "notion gotchas", "notion debugging".