API Rate Limits and Throttling

The Kibot API enforces concurrency and burst limits to keep the service responsive for every subscriber. This page documents the published numbers, what each error code means when a script trips a limit, and the backoff and parallelism patterns that work in practice. Most of the recurring "my script worked yesterday but is throwing errors today" cases trace back to one of three causes: too many concurrent connections, hitting the burst ceiling, or a stale session that re-authenticated mid-batch.

The Published Numbers

LimitValueScope
Recommended concurrent connections5Per account, across API + FTP + Kibot Agent
Hard ceiling, in-flight requests40Per account
Hard ceiling, new requests per 500 ms50Per account
Session idle timeout20 minutesPer login session
IP whitelist1 active IPPer subscription

The 5-connection guideline is the safe number for any production script. The 40 and 50-per-500ms ceilings are the points above which the rate limiter trips and starts returning errors. A small handful of customers run with higher parallelism after coordinating with support; the default account is capped at the published numbers.

What the Error Codes Mean

The API uses HTTP-style numeric codes in the response body. The relevant ones for rate limiting:

CodeMeaningWhat to do
401 Not Logged InSession expired or no active sessionRe-login and retry; check the 20-minute idle timeout
403 Login FailedAuth failed OR rate-limited; the code is overloadedIf credentials are correct, drop parallelism and retry with backoff
403 Too many connectionsBurst above the 40-in-flight or 50-per-500ms ceilingDrop concurrent workers to 5; add 100 to 500 ms between requests
407Authorization required for the requested symbol or endpointConfirm the symbol is in your purchased universe and the account has API access
498 Not AllowedEndpoint not allowed for this tier (e.g. tick from a guest session)Upgrade to Premium for the full surface
499 Not Allowed (account lacks full API access)The symbol is licensed but the account is not on PremiumUpgrade or contact support

The 403 code is reused for both authentication failure and rate-limiting, so a script that suddenly starts seeing 403 after a few hundred successful calls is almost always rate-limited rather than mis-authenticated. The disambiguation pattern: if a single test request from the same script with the same credentials succeeds after a 60-second pause, the prior batch was rate-limited.

Connections Are Shared Across API, FTP, and Agent

The concurrent-connection pool is per account, not per protocol. A scheduled Kibot Agent task pulling daily updates at 6 AM ET and a Python script running tick downloads in parallel against the same account consume the same five slots. The most common cause of "the Agent suddenly fails" on accounts that also run scripts is exactly this contention. If the script is running, the Agent's slot count drops, and vice versa.

The practical pattern is to schedule the Agent at a time when no script is running, or to drop the script's worker count by one or two for the duration of the Agent run.

A simple worker-pool implementation that respects the limits:

# Python: bulk download with 5 workers and exponential backoff
import time
import concurrent.futures
import requests

MAX_WORKERS = 5
BASE_DELAY = 0.1   # 100 ms between requests per worker

def fetch(symbol, attempt=0):
    url = f"http://api.kibot.com/?action=history&symbol={symbol}&interval=1&type=stocks"
    r = requests.get(url, timeout=60)
    if r.status_code in (401, 403):
        if attempt >= 4:
            return None
        time.sleep(2 ** attempt)   # 1s, 2s, 4s, 8s
        # re-login here if 401
        return fetch(symbol, attempt + 1)
    return r.text

with concurrent.futures.ThreadPoolExecutor(max_workers=MAX_WORKERS) as pool:
    results = list(pool.map(fetch, symbols))

Key points: cap workers at 5, retry on 401/403 with exponential backoff up to a few seconds, re-login before retrying on 401, and surface a hard failure after a small number of attempts so a sustained outage does not silently hang the batch.

Parallel Downloads Do Not Improve Throughput

A separate constraint that customers run into: more workers do not download faster. The bottleneck is the destination disk's write throughput, not the network or the API. Five concurrent file writes saturate most SSDs and NVMe drives; more than five workers create disk contention that slows the aggregate throughput. The 5-worker recommendation is a sweet spot for both the API limiter and the local disk, not just a server-side cap.

For bulk archive downloads (the full 20 GB stocks+ETFs package), a single download manager is often faster than 10 parallel API workers, because the manager's TCP window and disk buffering are optimised for sequential large files.

Session Handling for Long Batches

The API session times out after 20 minutes of idle. A batch that processes one slow symbol for 25 minutes will see the session expire mid-loop. Two strategies:

  • Re-login at fixed intervals (every 15 minutes) regardless of activity.
  • Catch 401 in the request loop, re-login, and retry once before failing the request.

The second pattern is cheaper because it only re-authenticates when needed, but the first is simpler if your batch is predictable. Both work; pick one and stick with it. See API authentication for the login endpoint and the explicit logout call.

How to Request a Higher Limit

Production workloads that genuinely need more than 5 concurrent connections can be reviewed case-by-case. Contact support with the account email, the use case, peak hours of operation, and a rough request-rate estimate. The team has lifted the cap for institutional users running synchronous reporting against fixed symbol panels; the cap stays in place by default to protect the rest of the subscriber base from a single-account burst.

Key Takeaways

  • 5 concurrent connections is the safe per-account number. The hard ceilings are 40 in flight and 50 new requests per 500 ms.
  • The connection pool is shared across API, FTP, and the Kibot Agent. Running all three at once on one account often triggers limits even when no single tool is over the per-tool guidance.
  • 403 Login Failed is reused for rate-limiting. If credentials are correct and a single test request succeeds after a pause, the prior batch was throttled.
  • Re-login on 401 and retry. Sessions expire after 20 minutes of idle.
  • More workers do not increase throughput. Local disk write speed caps useful parallelism at roughly 5 streams.
  • For genuinely high-volume institutional use, contact support to discuss raising the per-account cap.
  • How to get API access, plan tiers and per-tier endpoint matrix.
  • API authentication, login, logout, status, and the 20-minute session timeout.
  • Server responses, the full HTTP code table including responses outside the rate-limit context.
  • Compression, gzip negotiation and the bandwidth tradeoffs that interact with concurrency.
  • Data updates, scheduling the Kibot Agent and FTP refresh windows so they do not collide with scripted API work.
  • API client examples, reference clients in curl, Python, Rust, Go, TypeScript, R, C++, and .NET, all using the 5-worker pattern.