Skip to content

Rate Limits

API requests are rate limited to ensure fair usage and service stability.

Limits

EndpointLimitWindow
POST /api/v1/mockup60 requests60 seconds

Limits are applied per user (based on API key).

Response Headers

Every API response includes rate limit information in headers:

HeaderDescription
X-RateLimit-LimitMaximum requests allowed per window
X-RateLimit-RemainingRequests remaining in current window
X-RateLimit-ResetUnix timestamp when the limit resets

Example Response Headers

X-RateLimit-Limit: 60
X-RateLimit-Remaining: 45
X-RateLimit-Reset: 1705312800

Rate Limit Exceeded

When you exceed the rate limit, you'll receive a 429 Too Many Requests response:

json
{
  "error": "Too Many Requests",
  "message": "Rate limit exceeded. Try again in 30 seconds.",
  "retryAfter": 30
}

The response includes a Retry-After header indicating how many seconds to wait.

Handling Rate Limits

JavaScript

javascript
async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const response = await fetch(url, options);

    if (response.status === 429) {
      const retryAfter = parseInt(response.headers.get('Retry-After') || '60');
      console.log(`Rate limited. Waiting ${retryAfter}s...`);
      await new Promise(r => setTimeout(r, retryAfter * 1000));
      continue;
    }

    return response;
  }

  throw new Error('Max retries exceeded');
}

Python

python
import requests
import time

def fetch_with_retry(url, headers, json_body, max_retries=3):
    for i in range(max_retries):
        response = requests.post(url, headers=headers, json=json_body)

        if response.status_code == 429:
            retry_after = int(response.headers.get('Retry-After', 60))
            print(f'Rate limited. Waiting {retry_after}s...')
            time.sleep(retry_after)
            continue

        return response

    raise Exception('Max retries exceeded')

Best Practices

  1. Monitor remaining requests - Check X-RateLimit-Remaining to avoid hitting limits
  2. Implement backoff - Use exponential backoff for retries
  3. Queue requests - Spread requests over time instead of bursting
  4. Cache results - Store generated mockups to avoid redundant requests

Batch Processing Tips

When processing many screenshots:

javascript
// Process in batches with delays
const BATCH_SIZE = 10;
const DELAY_MS = 1000;

for (let i = 0; i < screenshots.length; i += BATCH_SIZE) {
  const batch = screenshots.slice(i, i + BATCH_SIZE);

  await Promise.all(batch.map(url => generateMockup(url)));

  // Wait between batches
  if (i + BATCH_SIZE < screenshots.length) {
    await new Promise(r => setTimeout(r, DELAY_MS));
  }
}

Shotprose API Documentation