Reference

Rate limits and quotas

Each API key can run 3 jobs at a time, create 500 jobs a day and upload 20 GB a day, with days counted in UTC. Over a limit, the API answers 429 RATE_LIMITED with a Retry-After header that says how many seconds to wait.

Files, durations and request fields have fixed limits too, all listed below.

Running at once
3 jobs
per key
Jobs a day
500
resets at midnight UTC
Uploads a day
20 GB
resets at midnight UTC

Rate limits#

Limits apply per API key. Each one answers 429 with its own message and Retry-After value.

Limiterror.messageRetry-After
3 jobs runningthis key already has 3 jobs running10 seconds
500 jobs a daythis key reached its 500 jobs per dayUntil midnight UTC
20 GB of uploads a daythis key reached its 20 GB of uploads per dayUntil midnight UTC
30 bad keys a minute from one IPtoo many failed auth attempts from your IP, retry in a minute60 seconds
  • A job holds one of its key's 3 slots from the create call until it succeeds or fails, including the time it waits in the queue.
  • Every job that starts counts toward the 500, including jobs that fail. Requests rejected with a 4xx don't count.
  • The upload budget counts the bytes of every POST /v1/uploads. Remote URLs you pass as inputs don't count.

Handling 429#

Wait the number of seconds in Retry-After, then send the same request again. To stay under the limit in the first place, queue work on your side and run at most 3 jobs per key at once.

429 Too Many Requests
{
  "error": {
    "code": "RATE_LIMITED",
    "message": "this key already has 3 jobs running"
  }
}
async function createJob(path, body) {
  while (true) {
    const res = await fetch(`https://api.reelsdk.com${path}`, {
      method: "POST",
      headers: {
        Authorization: `Bearer ${process.env.REELSDK_KEY}`,
        "Content-Type": "application/json",
      },
      body: JSON.stringify(body),
    });
    const json = await res.json();
    if (res.status !== 429) return json;

    // We only wait out short limits, a daily limit can take hours
    const seconds = Number(res.headers.get("Retry-After") ?? "10");
    if (seconds > 60) throw new Error(json.error.message);
    await new Promise((resolve) => setTimeout(resolve, seconds * 1000));
  }
}

Sizes and durations#

LimitValue
JSON request body2 MB
Upload with POST /v1/uploads100 MB
Input file, uploaded or remote500 MB
All inputs of one job1,000 MB
Video or audio input length15 minutes
Slideshow length15 minutes
Short length15 to 90 seconds
Job run time10 minutes
Files a job writes while it runs8 GB
Outputs of one job2 GB
Slideshow width and height240 to 2160 px
Image input100 megapixels
Wait on one request300 seconds
File retention7 days

Request fields#

FieldLimit
Slideshow images1 to 100
Slideshow voiceover.text10,000 characters
Captions words50,000 words
Captions prompt500 characters
Shorts topic500 characters
Shorts script3,000 characters and 90 seconds of narration
FFmpeg inputs50 files
FFmpeg outputs20 files
FFmpeg args1,000 arguments of 8,192 characters, or one 65,536 character string
FFmpeg timeout_s600 seconds
Any URL4,096 characters

Higher limits#

The defaults fit most apps, and limits can be raised per key. Email kevin@bitgate.com with what you're building and the numbers you need: jobs at once, jobs a day or upload volume.

Last updated 26 October 2026