Errors & Rate Limits

HTTP status codes, error response format, rate limiting details, and retry strategies for the ReelPlus API.

Storefront API

Error Response Format

All API errors return a consistent JSON structure:

{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "A human-readable description of what went wrong."
  }
}

HTTP Status Codes

StatusMeaningWhen It Occurs
200OKRequest succeeded
304Not ModifiedContent unchanged (cached)
400Bad RequestInvalid parameters or malformed request
401UnauthorizedMissing or invalid Authorization header
403ForbiddenInvalid/revoked API key or plan does not include API access
404Not FoundResource does not exist
429Too Many RequestsRate limit exceeded
500Internal Server ErrorUnexpected server error

Error Codes

400 — Bad Request

CodeMessageFix
INVALID_DATEInvalid date formatUse ISO 8601: YYYY-MM-DD
INVALID_DATE_RANGEstart_date after end_dateSwap your dates
INVALID_PARAMETERInvalid valueCheck endpoint docs
MISSING_PARAMETERRequired param missingInclude required params

401 — Unauthorized

CodeMessageFix
UNAUTHORIZEDMissing or invalid Authorization headerAdd Authorization: Bearer rp_xxx

403 — Forbidden

CodeMessageFix
INVALID_API_KEYKey not found or revokedCheck the key. In the sandbox, use the demo key from the API Overview
PLAN_LIMITPlan does not include API accessAPI access is available on Enterprise plans, on request

404 — Not Found

CodeMessageFix
NOT_FOUNDVideo not found / Widget not foundCheck the ID against the list endpoint

429 — Rate Limited

CodeMessageFix
RATE_LIMIT_EXCEEDEDToo many requestsWait and retry (see below)

Rate Limiting

Limits

ScopeLimitWindow
Per API Key60 requests1 minute (fixed window)

Response Headers

Every authenticated response includes (401 and 403 carry none, since no key was matched):

HeaderDescriptionExample
X-RateLimit-LimitMax requests per window60
X-RateLimit-RemainingRemaining in current window45
X-RateLimit-ResetUnix timestamp of reset1706540400

When exceeded, you also get Retry-After (seconds to wait).


Retry Strategy

Implement exponential backoff for production integrations:

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

    if (response.ok) return response.json();

    if (response.status === 429) {
      const retryAfter = response.headers.get("Retry-After");
      const wait = retryAfter
        ? parseInt(retryAfter, 10) * 1000
        : Math.pow(2, attempt) * 1000;
      await new Promise(r => setTimeout(r, wait));
      continue;
    }

    if (response.status >= 500) {
      await new Promise(r => setTimeout(r, Math.pow(2, attempt) * 1000));
      continue;
    }

    const error = await response.json();
    throw new Error(`${response.status}: ${error.error.message}`);
  }
  throw new Error("Max retries exceeded");
}
import time, requests

def fetch_with_retry(url, headers, params=None, max_retries=3):
    for attempt in range(max_retries):
        resp = requests.get(url, headers=headers, params=params)

        if resp.ok:
            return resp.json()

        if resp.status_code == 429:
            wait = int(resp.headers.get("Retry-After", 2 ** attempt))
            time.sleep(wait)
            continue

        if resp.status_code >= 500:
            time.sleep(2 ** attempt)
            continue

        raise Exception(f"{resp.status_code}: {resp.json()['error']['message']}")

    raise Exception("Max retries exceeded")

Never retry 401 or 403 errors — they require manual intervention (new key or plan upgrade). Only retry 429 and 5xx errors.