Ssemble API

Rate Limits

Understand the rate limiting applied to API requests.

Overview

The Ssemble API enforces rate limits to ensure fair usage and service stability. Limits vary by endpoint type — heavier operations like creating shorts have stricter limits than read-only endpoints.

Rate limits are applied per API key. If you have multiple API keys on the same account, each key has its own independent rate limit counters.


Rate limit layers

The API enforces rate limits at two levels:

  1. Per-endpoint limits — Each endpoint type has its own request-per-minute cap (see table below). These limits are per API key.
  2. Account-level limits — Hourly and daily caps applied across all endpoints. Default limits are 100 requests/hour and 1,000 requests/day. Higher-tier subscriptions receive increased limits (up to 2,000/hour and 20,000/day).

Both layers must pass for a request to succeed.

Limits by endpoint

EndpointRate limiterLimitWindow
POST /shorts/createVideo creation500 requests1 minute
GET /shorts/:id/statusStatus check500 requests1 minute
GET /shorts/:idStatus check500 requests1 minute
GET /shortsList requests500 requests1 minute
GET /musicStatus check500 requests1 minute
GET /game-videosStatus check500 requests1 minute
GET /meme-hooksStatus check500 requests1 minute
DELETE /shorts/:idStandard1,000 requests15 minutes
GET /templatesStandard1,000 requests15 minutes

Different endpoints use different rate limiter pools. Hitting the limit on POST /shorts/create does not affect your ability to call GET /shorts/:id/status.


Rate limit headers

Every API response includes these headers, regardless of whether the request succeeded or failed:

HeaderTypeDescription
X-RateLimit-Limit-HournumberMaximum requests allowed per hour
X-RateLimit-Remaining-HournumberRequests remaining in the current hour window
X-RateLimit-Limit-DaynumberMaximum requests allowed per day
X-RateLimit-Remaining-DaynumberRequests remaining today
X-RateLimit-ResetstringISO 8601 timestamp when the hourly limit resets

Reading headers in JavaScript

const response = await fetch('https://aiclipping.ssemble.com/api/v1/templates', {
  headers: { 'X-API-Key': 'sk_ssemble_your_key' }
});
 
const hourlyLimit = response.headers.get('X-RateLimit-Limit-Hour');
const hourlyRemaining = response.headers.get('X-RateLimit-Remaining-Hour');
const dailyRemaining = response.headers.get('X-RateLimit-Remaining-Day');
const resetAt = response.headers.get('X-RateLimit-Reset');
 
console.log(`Hourly: ${hourlyRemaining}/${hourlyLimit} remaining`);
console.log(`Daily: ${dailyRemaining} remaining`);
console.log(`Resets at: ${resetAt}`);

Reading headers in Python

response = requests.get(
    'https://aiclipping.ssemble.com/api/v1/templates',
    headers={'X-API-Key': os.environ['SSEMBLE_API_KEY']}
)
 
remaining = int(response.headers.get('X-RateLimit-Remaining-Hour', 0))
reset_at = response.headers.get('X-RateLimit-Reset', '')
 
print(f"Remaining this hour: {remaining}")
print(f"Resets at: {reset_at}")

Rate limit exceeded response

When you exceed a rate limit, the API returns a 429 Too Many Requests response:

Per-endpoint limit exceeded

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Too many video creation requests, please slow down.",
    "details": {
      "retryAfter": "2024-06-01T12:01:00.000Z"
    }
  }
}

Hourly account limit exceeded

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Hourly rate limit exceeded",
    "details": {
      "limit": 100,
      "reset": "2024-06-01T13:00:00.000Z"
    }
  }
}

Daily account limit exceeded

{
  "error": {
    "code": "rate_limit_exceeded",
    "message": "Daily rate limit exceeded",
    "details": {
      "limit": 1000,
      "reset": "2024-06-02T00:00:00.000Z"
    }
  }
}

The details object provides information about when you can retry. Use the retryAfter or reset timestamp to schedule your next request.


Handling rate limits

Exponential backoff

When you receive a 429 response, implement exponential backoff to avoid hammering the API:

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let attempt = 0; attempt <= maxRetries; attempt++) {
    const response = await fetch(url, options);
 
    if (response.status !== 429) {
      return response;
    }
 
    if (attempt === maxRetries) {
      throw new Error('Rate limit exceeded after max retries');
    }
 
    // Check the reset header first (ISO 8601 timestamp)
    const resetAt = response.headers.get('X-RateLimit-Reset');
    let waitMs;
 
    if (resetAt) {
      waitMs = Math.max(new Date(resetAt).getTime() - Date.now(), 1000);
    } else {
      // Exponential backoff: 1s, 2s, 4s
      waitMs = Math.pow(2, attempt) * 1000;
    }
 
    console.log(`Rate limited. Waiting ${Math.ceil(waitMs / 1000)}s before retry...`);
    await new Promise(r => setTimeout(r, waitMs));
  }
}

Pre-emptive rate limit checking

Instead of waiting for a 429 error, check remaining limits before making requests:

async function safeApiCall(url, options) {
  const response = await fetch(url, options);
 
  const remaining = parseInt(response.headers.get('X-RateLimit-Remaining-Hour') || '999');
  if (remaining < 5) {
    console.warn(`Warning: Only ${remaining} requests remaining this hour`);
  }
 
  return response;
}

Best practices

  • Poll at 10-second intervals — When checking status, don't poll faster than every 10 seconds. Faster polling wastes your rate limit budget without gaining useful information.

  • Use the list endpoint for batch monitoring — If you have many active requests, use GET /shorts with status filtering instead of polling each request individually. One call to the list endpoint replaces many individual status calls.

    # Instead of polling 20 individual requests:
    curl -H "X-API-Key: sk_ssemble_your_key" \
      "https://aiclipping.ssemble.com/api/v1/shorts?status=processing&limit=100"
  • Cache stable data — Template lists (GET /templates) and asset lists (GET /music, GET /game-videos, GET /meme-hooks) change infrequently. Cache these responses for at least 1 hour to reduce API calls.

  • Check remaining quota — Read X-RateLimit-Remaining-Hour and X-RateLimit-Remaining-Day headers to plan your request volume. Spread requests over time instead of sending bursts.

  • Handle 429 gracefully — Always implement retry logic with backoff. Never loop without delay when receiving rate limit errors.

  • Use the reset timestamp — The X-RateLimit-Reset header (ISO 8601 format) tells you exactly when the hourly limit resets. Schedule your retries to align with this time instead of guessing.

Ssemble Logo
Copyright © 2026 Ssemble Inc.
All rights reserved