Agent Skills: Adobe Rate Limits

|

UncategorizedID: jeremylongshore/claude-code-plugins-plus-skills/adobe-rate-limits

Install this agent skill to your local

pnpm dlx add-skill https://github.com/jeremylongshore/claude-code-plugins-plus-skills/tree/HEAD/plugins/saas-packs/adobe-pack/skills/adobe-rate-limits

Skill Files

Browse the full folder contents for adobe-rate-limits.

Download Skill

Loading file tree…

plugins/saas-packs/adobe-pack/skills/adobe-rate-limits/SKILL.md

Skill Metadata

Name
adobe-rate-limits
Description
|

Adobe Rate Limits

Overview

Handle Adobe API rate limits gracefully with exponential backoff, Retry-After header support, and proactive quota management. Each Adobe API has different rate limits.

Prerequisites

  • Adobe SDK installed and authenticated
  • Understanding of async/await patterns
  • Awareness of your API tier and entitlements

Instructions

Step 1: Know Your Rate Limits by API

| API | Limit | Scope | Response | |-----|-------|-------|----------| | Firefly API | ~20 req/min (trial), higher on paid | Per api-key | 429 + Retry-After | | PDF Services | 500 tx/month (free), unlimited (paid) | Per credential | 429 or QUOTA_EXCEEDED | | Photoshop API | Varies by entitlement | Per api-key | 429 + Retry-After | | Lightroom API | Varies by entitlement | Per api-key | 429 + Retry-After | | I/O Events Publishing | 3,000 req/5sec | Per api-key | 429 + Retry-After | | Analytics 2.0 API | 12 req/6sec per user (~120 req/min) | Per user | 429 + Retry-After | | IMS Token Endpoint | ~100 req/min | Per client_id | 429 |

Step 2: Implement Retry-After Aware Backoff

// src/adobe/rate-limiter.ts
import { AdobeApiError } from './client';

export async function withAdobeBackoff<T>(
  operation: () => Promise<T>,
  config = { maxRetries: 5, baseDelayMs: 1000, maxDelayMs: 60_000 }
): Promise<T> {
  for (let attempt = 0; attempt <= config.maxRetries; attempt++) {
    try {
      return await operation();
    } catch (error: any) {
      if (attempt === config.maxRetries) throw error;

      // Only retry on 429 and 5xx
      const status = error.status || error.response?.status;
      if (status && status !== 429 && (status < 500 || status >= 600)) throw error;

      // Honor Adobe's Retry-After header (seconds)
      let delay: number;
      if (error.retryAfter) {
        delay = error.retryAfter * 1000;
      } else {
        // Exponential backoff with jitter
        const exponential = config.baseDelayMs * Math.pow(2, attempt);
        const jitter = Math.random() * config.baseDelayMs;
        delay = Math.min(exponential + jitter, config.maxDelayMs);
      }

      console.warn(
        `Adobe rate limited (attempt ${attempt + 1}/${config.maxRetries}). ` +
        `Waiting ${(delay / 1000).toFixed(1)}s...`
      );
      await new Promise(r => setTimeout(r, delay));
    }
  }
  throw new Error('Unreachable');
}

Step 3: Proactive Rate Tracking

// Track remaining quota from response headers
class AdobeRateTracker {
  private remaining: number = Infinity;
  private resetAt: number = 0;

  updateFromResponse(response: Response): void {
    const remaining = response.headers.get('Retry-After');
    // Adobe primarily uses Retry-After rather than X-RateLimit-* headers
    // Some APIs (Analytics, Events) include additional rate info
    if (remaining) {
      this.remaining = 0;
      this.resetAt = Date.now() + parseInt(remaining) * 1000;
    }
  }

  async waitIfNeeded(): Promise<void> {
    if (this.remaining <= 0 && Date.now() < this.resetAt) {
      const waitMs = this.resetAt - Date.now();
      console.log(`Proactively waiting ${waitMs}ms for Adobe rate limit reset`);
      await new Promise(r => setTimeout(r, waitMs));
      this.remaining = Infinity; // Reset after wait
    }
  }
}

Step 4: Queue-Based Rate Limiting for Batch Operations

import PQueue from 'p-queue';

// Configure queue per API — match to known rate limits
const fireflyQueue = new PQueue({
  concurrency: 2,        // Max concurrent requests
  interval: 3000,        // Time window (ms)
  intervalCap: 1,        // Max requests per interval
});

const pdfServicesQueue = new PQueue({
  concurrency: 5,
  interval: 1000,
  intervalCap: 5,
});

const eventsQueue = new PQueue({
  concurrency: 10,
  interval: 5000,
  intervalCap: 3000,     // Match Adobe's 3000/5sec limit
});

// Usage
async function batchFireflyGenerate(prompts: string[]) {
  const results = await Promise.all(
    prompts.map(prompt =>
      fireflyQueue.add(() =>
        withAdobeBackoff(() => generateImage({ prompt }))
      )
    )
  );
  return results;
}

Step 5: PDF Services Transaction Monitoring

// Track monthly PDF Services usage against free tier limit
class PdfServicesQuotaTracker {
  private transactionsUsed = 0;
  private readonly monthlyLimit: number;

  constructor(tier: 'free' | 'paid' = 'free') {
    this.monthlyLimit = tier === 'free' ? 500 : Infinity;
  }

  recordTransaction(): void {
    this.transactionsUsed++;
    const remaining = this.monthlyLimit - this.transactionsUsed;

    if (remaining <= 50) {
      console.warn(`PDF Services: ${remaining} transactions remaining this month`);
    }
    if (remaining <= 0) {
      throw new Error('PDF Services monthly quota exceeded. Upgrade plan or wait for reset.');
    }
  }

  getUsage(): { used: number; limit: number; remaining: number } {
    return {
      used: this.transactionsUsed,
      limit: this.monthlyLimit,
      remaining: Math.max(0, this.monthlyLimit - this.transactionsUsed),
    };
  }
}

Output

  • Retry logic that honors Adobe Retry-After headers
  • Per-API queue-based rate limiting for batch operations
  • Monthly transaction tracking for PDF Services free tier
  • Proactive backpressure before hitting limits

Error Handling

| Scenario | Detection | Action | |----------|-----------|--------| | Single 429 | Retry-After header | Wait specified seconds, retry | | Sustained 429s | Multiple retries fail | Reduce concurrency; check tier | | PDF QUOTA_EXCEEDED | Monthly limit hit | Upgrade tier or wait for reset | | Events 429 | 3000/5sec exceeded | Reduce batch size or add queue |

Resources

Next Steps

For security configuration, see adobe-security-basics.