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".

25 stars

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

$curl -o ~/.claude/skills/canva-known-pitfalls/SKILL.md --create-dirs "https://raw.githubusercontent.com/ComeOnOliver/skillshub/main/skills/jeremylongshore/claude-code-plugins-plus-skills/canva-known-pitfalls/SKILL.md"

Manual Installation

  1. Download SKILL.md from GitHub
  2. Place it in .claude/skills/canva-known-pitfalls/SKILL.md inside your project
  3. Restart your AI agent — it will auto-discover the skill

How canva-known-pitfalls Compares

Feature / Agentcanva-known-pitfallsStandard Approach
Platform SupportNot specifiedLimited / Varies
Context Awareness High Baseline
Installation ComplexityUnknownN/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.

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

exa-known-pitfalls

25
from ComeOnOliver/skillshub

Identify and avoid Exa anti-patterns and common integration mistakes. Use when reviewing Exa code, onboarding new developers, or auditing existing Exa integrations for correctness. Trigger with phrases like "exa mistakes", "exa anti-patterns", "exa pitfalls", "exa what not to do", "exa code review".

customerio-known-pitfalls

25
from ComeOnOliver/skillshub

Identify and avoid Customer.io anti-patterns and gotchas. Use when reviewing integrations, onboarding developers, or auditing existing Customer.io code. Trigger: "customer.io mistakes", "customer.io anti-patterns", "customer.io gotchas", "customer.io pitfalls", "customer.io code review".

cursor-known-pitfalls

25
from ComeOnOliver/skillshub

Avoid common Cursor IDE pitfalls: AI feature mistakes, security gotchas, configuration errors, and team workflow issues. Triggers on "cursor pitfalls", "cursor mistakes", "cursor gotchas", "cursor issues", "cursor problems", "cursor tips".

clay-known-pitfalls

25
from ComeOnOliver/skillshub

Identify and avoid the top Clay anti-patterns, gotchas, and integration mistakes. Use when reviewing Clay integrations for issues, onboarding new team members, or auditing existing Clay table configurations. Trigger with phrases like "clay mistakes", "clay anti-patterns", "clay pitfalls", "clay what not to do", "clay gotchas", "clay code review".

clade-known-pitfalls

25
from ComeOnOliver/skillshub

Common mistakes when building with the Anthropic API and how to avoid them. Use when working with known-pitfalls patterns. Trigger with "anthropic mistakes", "claude pitfalls", "anthropic gotchas", "common claude errors", "anthropic anti-patterns".

canva-webhooks-events

25
from ComeOnOliver/skillshub

Implement Canva Connect API webhook handling with JWK signature verification. Use when setting up webhook endpoints, handling Canva event notifications, or implementing real-time design collaboration features. Trigger with phrases like "canva webhook", "canva events", "canva notifications", "handle canva events", "canva JWK".

canva-upgrade-migration

25
from ComeOnOliver/skillshub

Plan and execute Canva Connect API version upgrades and breaking change detection. Use when Canva releases API changes, migrating brand template IDs, or adapting to endpoint deprecations. Trigger with phrases like "upgrade canva", "canva API changes", "canva breaking changes", "canva deprecation", "canva changelog".

canva-security-basics

25
from ComeOnOliver/skillshub

Apply Canva Connect API security best practices for OAuth tokens and access control. Use when securing OAuth credentials, implementing least-privilege scopes, or auditing Canva integration security. Trigger with phrases like "canva security", "canva secrets", "secure canva", "canva token security", "canva OAuth security".

canva-sdk-patterns

25
from ComeOnOliver/skillshub

Apply production-ready Canva Connect API client patterns for TypeScript and Python. Use when building a reusable API client, implementing token refresh, or establishing team coding standards for Canva integrations. Trigger with phrases like "canva client patterns", "canva best practices", "canva code patterns", "canva API wrapper", "canva TypeScript client".

canva-reliability-patterns

25
from ComeOnOliver/skillshub

Implement reliability patterns for Canva Connect API — circuit breakers, idempotency, graceful degradation. Use when building fault-tolerant Canva integrations, implementing retry strategies, or adding resilience to production Canva services. Trigger with phrases like "canva reliability", "canva circuit breaker", "canva resilience", "canva fallback", "canva fault tolerance".

canva-reference-architecture

25
from ComeOnOliver/skillshub

Implement Canva Connect API reference architecture with best-practice project layout. Use when designing new Canva integrations, reviewing project structure, or establishing architecture standards for Canva applications. Trigger with phrases like "canva architecture", "canva project structure", "how to organize canva", "canva layout", "canva reference".

canva-rate-limits

25
from ComeOnOliver/skillshub

Handle Canva Connect API rate limits with backoff, queuing, and monitoring. Use when hitting 429 errors, implementing retry logic, or optimizing API request throughput for Canva integrations. Trigger with phrases like "canva rate limit", "canva throttling", "canva 429", "canva retry", "canva backoff".