juicebox-rate-limits
Adds rate limiting and backoff logic to Juicebox API requests.
Install
mkdir -p .claude/skills/juicebox-rate-limits && curl -L -o skill.zip "https://agentskills.codes/api/skills/download/2743" && unzip -o skill.zip -d .claude/skills/juicebox-rate-limits && rm skill.zipInstalls to .claude/skills/juicebox-rate-limits
Activation
This is the description your AI agent reads to decide when to run this skill — the better it matches your request, the more reliably it fires.
Implement Juicebox rate limiting.Key capabilities
- →Implement plan-tiered rate limits
- →Manage API request queues
- →Apply retry strategies with exponential backoff
- →Handle 429 (Too Many Requests) responses
- →Process batch operations with spacing
How it works
This skill implements a token bucket rate limiter and a retry strategy with exponential backoff to manage Juicebox API requests, ensuring compliance with various endpoint-specific rate limits.
Inputs & outputs
When to use juicebox-rate-limits
- →Implement request retries
- →Handle API throttling
- →Optimize request throughput
About this skill
Juicebox Rate Limits
Overview
Juicebox's AI-powered data analysis API enforces plan-tiered rate limits across dataset uploads, analysis triggers, and result retrieval. Heavy analytical workloads like running comparative analyses across multiple datasets or batch-processing survey results hit the analysis trigger limit first. The enrichment endpoints for augmenting datasets with external data sources have separate, lower caps, making it essential to prioritize enrichment calls and batch analysis runs during off-peak windows.
Rate Limit Reference
| Endpoint | Limit | Window | Scope |
|---|---|---|---|
| Dataset upload | 20 req | 1 minute | Per API key |
| Analysis trigger | 30 req | 1 minute | Per API key |
| Result retrieval | 120 req | 1 minute | Per API key |
| Data enrichment | 15 req | 1 minute | Per API key |
| Export download | 10 req | 1 minute | Per API key |
Rate Limiter Implementation
class JuiceboxRateLimiter {
private tokens: number;
private lastRefill: number;
private readonly max: number;
private readonly refillRate: number;
private queue: Array<{ resolve: () => void }> = [];
constructor(maxPerMinute: number) {
this.max = maxPerMinute;
this.tokens = maxPerMinute;
this.lastRefill = Date.now();
this.refillRate = maxPerMinute / 60_000;
}
async acquire(): Promise<void> {
this.refill();
if (this.tokens >= 1) { this.tokens -= 1; return; }
return new Promise(resolve => this.queue.push({ resolve }));
}
private refill() {
const now = Date.now();
this.tokens = Math.min(this.max, this.tokens + (now - this.lastRefill) * this.refillRate);
this.lastRefill = now;
while (this.tokens >= 1 && this.queue.length) {
this.tokens -= 1;
this.queue.shift()!.resolve();
}
}
}
const analysisLimiter = new JuiceboxRateLimiter(25);
const enrichLimiter = new JuiceboxRateLimiter(12);
Retry Strategy
async function juiceboxRetry<T>(
limiter: JuiceboxRateLimiter, fn: () => Promise<Response>, maxRetries = 3
): Promise<T> {
for (let attempt = 0; attempt <= maxRetries; attempt++) {
await limiter.acquire();
const res = await fn();
if (res.ok) return res.json();
if (res.status === 429) {
const retryAfter = parseInt(res.headers.get("Retry-After") || "15", 10);
const jitter = Math.random() * 3000;
await new Promise(r => setTimeout(r, retryAfter * 1000 + jitter));
continue;
}
if (res.status >= 500 && attempt < maxRetries) {
await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 2000));
continue;
}
throw new Error(`Juicebox API ${res.status}: ${await res.text()}`);
}
throw new Error("Max retries exceeded");
}
Batch Processing
async function batchAnalyzeDatasets(datasetIds: string[], query: string, batchSize = 5) {
const results: any[] = [];
for (let i = 0; i < datasetIds.length; i += batchSize) {
const batch = datasetIds.slice(i, i + batchSize);
const batchResults = await Promise.all(
batch.map(id => juiceboxRetry(analysisLimiter, () =>
fetch(`${BASE}/api/v1/datasets/${id}/analyze`, {
method: "POST", headers,
body: JSON.stringify({ query }),
})
))
);
results.push(...batchResults);
if (i + batchSize < datasetIds.length) await new Promise(r => setTimeout(r, 8000));
}
return results;
}
Error Handling
| Issue | Cause | Fix |
|---|---|---|
| 429 on analysis trigger | Exceeded 30 req/min analysis cap | Queue analyses, space 3s apart |
| 429 on enrichment | Enrichment limit (15/min) is lowest | Batch enrichments separately with wider spacing |
| Upload timeout | Dataset exceeds 50MB | Compress CSV, use chunked upload endpoint |
| Analysis still processing | Complex query on large dataset | Poll status every 10s, timeout at 10 min |
| 403 on export | Plan does not include export feature | Verify plan tier supports data export |
Resources
- Juicebox API Documentation
Next Steps
See juicebox-performance-tuning.
When not to use it
- →When API rate limits are not a concern
- →When real-time processing without delays is critical
Limitations
- →Analysis trigger limit is 30 requests per minute per API key
- →Data enrichment limit is 15 requests per minute per API key
- →Batch processing requires spacing between batches to avoid rate limits
How it compares
This approach proactively manages API request frequency and retries, preventing 429 errors and ensuring stable performance, unlike making unthrottled requests that can lead to service interruptions.
Compared to similar skills
juicebox-rate-limits side by side with the closest alternatives in the catalog.
| Skill | Installs | Updated | Safety | Difficulty |
|---|---|---|---|---|
| juicebox-rate-limits (this skill) | 2 | 25d | No flags | Advanced |
| mcporter | 7 | 2mo | No flags | Intermediate |
| calcom-api | 2 | 3mo | No flags | Intermediate |
| dust-mcp-server | 1 | 25d | Review | Advanced |
Try saying
Example prompts that trigger this skill in your AI assistant.
More by jeremylongshore
View all by jeremylongshore →You might also like
mcporter
openclaw
Use the mcporter CLI to list, configure, auth, and call MCP servers/tools directly (HTTP or stdio), including ad-hoc servers, config edits, and CLI/type generation.
calcom-api
calcom
Interact with the Cal.com API v2 to manage scheduling, bookings, event types, availability, and calendars. Use this skill when building integrations that need to create or manage bookings, check availability, configure event types, or sync calendars with Cal.com's scheduling infrastructure.
dust-mcp-server
dust-tt
Step-by-step guide for creating new internal MCP server integrations in Dust that connect to remote platforms (Jira, HubSpot, Salesforce, etc.). Use when adding a new MCP server, implementing a platform integration, or connecting Dust to a new external service.
developing-genkit-tooling
firebase
Best practices for authoring Genkit tooling, including CLI commands and MCP server tools. Covers naming conventions, architectural patterns, and consistency guidelines.
clay-sdk-patterns
jeremylongshore
Apply production-ready Clay SDK patterns for TypeScript and Python. Use when implementing Clay integrations, refactoring SDK usage, or establishing team coding standards for Clay. Trigger with phrases like "clay SDK patterns", "clay best practices", "clay code patterns", "idiomatic clay".
vercel-sdk-patterns
jeremylongshore
Execute apply production-ready Vercel SDK patterns for TypeScript and Python. Use when implementing Vercel integrations, refactoring SDK usage, or establishing team coding standards for Vercel. Trigger with phrases like "vercel SDK patterns", "vercel best practices", "vercel code patterns", "idiomatic vercel".