Skip to content

Rate limits

The API rate-limits each account with a fixed window per endpoint class. Over a limit returns 429 rate_limited with a Retry-After header (seconds to wait).

Limits

Limits are per account, in a rolling fixed window (default 60 seconds):

BucketDefaultCovers
Job creation20 / windowPOST /jobs — the expensive path (enqueues work + spends balance).

Polling (GET /jobs/{id}) and downloads are not part of this bucket, but poll politely — every 1–2 seconds per job is plenty.

Exact numbers can be tuned per deployment/plan. Read the effective ceilings from GET /options (limits) and treat the 429 + Retry-After contract as the source of truth, not a hardcoded number.

Handling 429

When you hit a limit:

HTTP/1.1 429 Too Many Requests
Retry-After: 12
json
{ "error": "rate_limited", "message": "Rate limit exceeded. Retry in 12s." }

Back off for Retry-After seconds, then retry. A simple, robust pattern:

python
import time, requests

def with_retry(fn, tries=5):
    for _ in range(tries):
        r = fn()
        if r.status_code != 429:
            return r
        time.sleep(int(r.headers.get("Retry-After", "5")))
    return r  # give up after `tries` — surface the 429

Staying under the limits

  • Batch with copies, not with many jobs. One job with copies: 20 is a single creation call; twenty separate jobs is twenty. Fanning out inside a job is cheaper and faster.
  • Poll, don't hammer. One in-flight poll per job every 1–2 seconds is ample.
  • Pre-upload large sources once with inputKey and reuse the key across jobs rather than re-uploading.

FluidGhost API — part of the Fluidvip ecosystem.