Claude-code-plugins-plus-skills fireflies-rate-limits
install
source · Clone the upstream repo
git clone https://github.com/jeremylongshore/claude-code-plugins-plus-skills
Claude Code · Install into ~/.claude/skills/
T=$(mktemp -d) && git clone --depth=1 https://github.com/jeremylongshore/claude-code-plugins-plus-skills "$T" && mkdir -p ~/.claude/skills && cp -r "$T/plugins/saas-packs/fireflies-pack/skills/fireflies-rate-limits" ~/.claude/skills/jeremylongshore-claude-code-plugins-plus-skills-fireflies-rate-limits && rm -rf "$T"
manifest:
plugins/saas-packs/fireflies-pack/skills/fireflies-rate-limits/SKILL.mdsource content
Fireflies.ai Rate Limits
Overview
Handle Fireflies.ai GraphQL API rate limits with exponential backoff and request queuing. Fireflies enforces per-plan limits and per-operation limits.
Rate Limit Reference
Per-Plan Limits
| Plan | Limit | Scope |
|---|---|---|
| Free | 50 requests/day | Per API key |
| Pro | 50 requests/day | Per API key |
| Business | 60 requests/min | Per API key |
| Enterprise | 60 requests/min | Per API key |
Per-Operation Limits
| Operation | Limit | Error Code |
|---|---|---|
| 3 per 20 minutes | |
| 10 per hour (up to 50 emails each) | |
| 10 per minute | |
| Varies by plan | |
Instructions
Step 1: Detect Rate Limits in Responses
interface FirefliesError { message: string; code: string; extensions?: { status: number }; } function isRateLimited(response: any): boolean { return response.errors?.some( (e: FirefliesError) => e.code === "too_many_requests" || e.extensions?.status === 429 ); }
Step 2: Exponential Backoff with Jitter
async function firefliesQueryWithRetry<T>( query: string, variables?: Record<string, any>, maxRetries = 5 ): Promise<T> { const FIREFLIES_API = "https://api.fireflies.ai/graphql"; for (let attempt = 0; attempt <= maxRetries; attempt++) { const res = await fetch(FIREFLIES_API, { method: "POST", headers: { "Content-Type": "application/json", Authorization: `Bearer ${process.env.FIREFLIES_API_KEY}`, }, body: JSON.stringify({ query, variables }), }); const json = await res.json(); if (!isRateLimited(json)) { if (json.errors) throw new Error(json.errors[0].message); return json.data; } if (attempt === maxRetries) { throw new Error(`Rate limited after ${maxRetries} retries`); } // Exponential backoff: 1s, 2s, 4s, 8s, 16s + jitter const baseDelay = 1000 * Math.pow(2, attempt); const jitter = Math.random() * 500; const delay = Math.min(baseDelay + jitter, 32000); console.log(`Rate limited. Retry ${attempt + 1}/${maxRetries} in ${delay.toFixed(0)}ms`); await new Promise(r => setTimeout(r, delay)); } throw new Error("Unreachable"); }
Step 3: Request Queue for Batch Operations
import PQueue from "p-queue"; // Business plan: 60 req/min = 1 req/sec safe rate const firefliesQueue = new PQueue({ concurrency: 1, interval: 1100, intervalCap: 1, }); async function queuedQuery<T>(query: string, variables?: Record<string, any>): Promise<T> { return firefliesQueue.add(() => firefliesQueryWithRetry<T>(query, variables)); } // Batch fetch transcripts without hitting rate limits async function batchFetchTranscripts(ids: string[]) { const results = []; for (const id of ids) { const data = await queuedQuery(` query GetTranscript($id: String!) { transcript(id: $id) { id title date duration summary { overview action_items } } } `, { id }); results.push(data); } return results; }
Step 4: Free/Pro Plan Daily Budget Tracker
class DailyBudgetTracker { private count = 0; private resetDate = new Date().toDateString(); private readonly dailyLimit: number; constructor(plan: "free" | "pro" | "business") { this.dailyLimit = plan === "business" ? Infinity : 50; } canRequest(): boolean { this.resetIfNewDay(); return this.count < this.dailyLimit; } record(): void { this.resetIfNewDay(); this.count++; } remaining(): number { this.resetIfNewDay(); return Math.max(0, this.dailyLimit - this.count); } private resetIfNewDay(): void { const today = new Date().toDateString(); if (today !== this.resetDate) { this.count = 0; this.resetDate = today; } } } const budget = new DailyBudgetTracker("pro"); if (!budget.canRequest()) { console.log("Daily API limit reached. Try again tomorrow."); }
Error Handling
| Scenario | Detection | Action |
|---|---|---|
| 429 response | | Exponential backoff |
| Daily limit hit (Free/Pro) | Track request count | Wait until next day |
throttle | 3 per 20 min | Queue with 7-min spacing |
| Burst of webhook events | Many transcripts at once | Queue transcript fetches |
Output
- Rate-limit-aware GraphQL client with automatic retry
- Request queue preventing burst-induced throttling
- Daily budget tracker for Free/Pro plans
Resources
Next Steps
For security configuration, see
fireflies-security-basics.