Agent skill
canva-rate-limits
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".
Install this agent skill to your Project
npx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/main/plugins/saas-packs/canva-pack/skills/canva-rate-limits
SKILL.md
Canva Rate Limits
Overview
The Canva Connect API enforces per-user, per-endpoint rate limits. Each endpoint has different thresholds. A 429 response means you must wait before retrying.
Canva Connect API Rate Limits
| Endpoint | Method | Limit |
|---|---|---|
/v1/users/me |
GET | 10 req/min |
/v1/users/me/profile |
GET | 10 req/min |
/v1/designs |
GET | 100 req/min |
/v1/designs |
POST | 20 req/min |
/v1/designs/{id} |
GET | 100 req/min |
/v1/exports |
POST | 75 req/5min, 500/24hr per user |
/v1/exports (integration) |
POST | 750 req/5min, 5000/24hr |
/v1/exports (per document) |
POST | 75 req/5min |
/v1/asset-uploads |
POST | 30 req/min |
/v1/autofills |
POST | 60 req/min |
/v1/folders |
POST | 20 req/min |
/v1/brand-templates |
GET | 100 req/min |
All limits are per user of your integration unless noted otherwise.
Exponential Backoff with Jitter
async function canvaRequestWithBackoff<T>(
fn: () => Promise<T>,
config = { maxRetries: 5, baseDelayMs: 1000, maxDelayMs: 60000 }
): Promise<T> {
for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
try {
return await fn();
} catch (error: any) {
if (attempt === config.maxRetries) throw error;
// Only retry on 429 or 5xx
const status = error.status || error.response?.status;
if (status !== 429 && (status < 500 || status >= 600)) throw error;
// Honor Retry-After header if present
const retryAfter = error.headers?.get?.('Retry-After');
const delay = retryAfter
? parseInt(retryAfter) * 1000
: Math.min(
config.baseDelayMs * Math.pow(2, attempt) + Math.random() * 1000,
config.maxDelayMs
);
console.warn(`Rate limited (attempt ${attempt + 1}/${config.maxRetries}). Waiting ${(delay / 1000).toFixed(1)}s`);
await new Promise(r => setTimeout(r, delay));
}
}
throw new Error('Unreachable');
}
Queue-Based Rate Limiting
import PQueue from 'p-queue';
// Match per-user endpoint limits
const canvaQueues = {
designs: new PQueue({ concurrency: 1, interval: 3000, intervalCap: 1 }), // ~20/min
exports: new PQueue({ concurrency: 1, interval: 4000, intervalCap: 1 }), // ~15/min (conservative)
assets: new PQueue({ concurrency: 1, interval: 2000, intervalCap: 1 }), // ~30/min
reads: new PQueue({ concurrency: 3, interval: 1000, intervalCap: 3 }), // ~100/min (shared reads)
};
// Usage — automatically queued to stay under limits
const design = await canvaQueues.designs.add(() =>
client.createDesign({ design_type: { type: 'custom', width: 1080, height: 1080 }, title: 'Queued' })
);
// Batch export with rate control
const designIds = ['DAV1', 'DAV2', 'DAV3', 'DAV4', 'DAV5'];
const exports = await Promise.all(
designIds.map(id =>
canvaQueues.exports.add(() =>
client.createExport({ design_id: id, format: { type: 'pdf' } })
)
)
);
Rate Limit Monitor
class CanvaRateLimitTracker {
private windows: Map<string, { count: number; resetAt: number }> = new Map();
track(endpoint: string, response: Response): void {
const remaining = response.headers.get('X-RateLimit-Remaining');
const reset = response.headers.get('X-RateLimit-Reset');
if (remaining !== null) {
this.windows.set(endpoint, {
count: parseInt(remaining),
resetAt: reset ? parseInt(reset) * 1000 : Date.now() + 60000,
});
}
}
shouldThrottle(endpoint: string): boolean {
const window = this.windows.get(endpoint);
if (!window) return false;
return window.count < 3 && Date.now() < window.resetAt;
}
getWaitMs(endpoint: string): number {
const window = this.windows.get(endpoint);
if (!window) return 0;
return Math.max(0, window.resetAt - Date.now());
}
report(): Record<string, { remaining: number; resetsIn: string }> {
const report: Record<string, any> = {};
for (const [ep, w] of this.windows) {
report[ep] = {
remaining: w.count,
resetsIn: `${Math.max(0, (w.resetAt - Date.now()) / 1000).toFixed(0)}s`,
};
}
return report;
}
}
Proactive Throttling
// Wrap the client to throttle before hitting limits
async function throttledCanvaRequest<T>(
tracker: CanvaRateLimitTracker,
endpoint: string,
fn: () => Promise<T>
): Promise<T> {
if (tracker.shouldThrottle(endpoint)) {
const waitMs = tracker.getWaitMs(endpoint);
console.log(`Proactively waiting ${waitMs}ms for ${endpoint}`);
await new Promise(r => setTimeout(r, waitMs));
}
return fn();
}
Error Handling
| Scenario | Detection | Action |
|---|---|---|
| Single 429 | HTTP status | Wait Retry-After seconds, retry |
| Sustained 429s | Multiple retries fail | Reduce request rate, increase backoff |
| Export quota hit | 500/24hr per user | Queue exports, spread across hours |
| Integration quota | 5000/24hr exports | Distribute across users |
Resources
Next Steps
For security configuration, see canva-security-basics.
Recommended Agent Skills
Expand your agent's capabilities with these related and highly-rated skills.
dockerfile-generator
Dockerfile Generator - Auto-activating skill for DevOps Basics. Triggers on: dockerfile generator, dockerfile generator Part of the DevOps Basics skill category.
branch-naming-helper
Branch Naming Helper - Auto-activating skill for DevOps Basics. Triggers on: branch naming helper, branch naming helper Part of the DevOps Basics skill category.
readme-generator
Readme Generator - Auto-activating skill for DevOps Basics. Triggers on: readme generator, readme generator Part of the DevOps Basics skill category.
makefile-generator
Makefile Generator - Auto-activating skill for DevOps Basics. Triggers on: makefile generator, makefile generator Part of the DevOps Basics skill category.
gitignore-generator
Gitignore Generator - Auto-activating skill for DevOps Basics. Triggers on: gitignore generator, gitignore generator Part of the DevOps Basics skill category.
pre-commit-hook-setup
Pre Commit Hook Setup - Auto-activating skill for DevOps Basics. Triggers on: pre commit hook setup, pre commit hook setup Part of the DevOps Basics skill category.
Didn't find tool you were looking for?