Skip to main content

open-keypool

Minimal Python library for pooling and rotating API keys to avoid HTTP 429 rate-limit errors. Provide a list of keys (or pull them from Doppler, .env, or JSON), choose a rotation strategy (round-robin or least-recently-used), and the pool handles cooldown on rate-limit responses and permanent disablement on invalid keys — all thread-safe.

Install

pip install open-keypool

Quickstart

Local keys array

from open_keypool import KeyPool, AllKeysExhaustedError, KeyState

pool = KeyPool(keys=["sk-key1", "sk-key2", "sk-key3"], strategy="round_robin")

for attempt in range(pool.max_retries):
    key = pool.get_key()
    response = call_your_api(key)

    # Feed the response — the pool decides success / cooldown / disable
    new_state = pool.handle_response(
        key, response.status_code,
        headers=dict(response.headers),
        body=response.json(),
    )

    if new_state == KeyState.ACTIVE:
        break  # success
    elif new_state == KeyState.COOLDOWN:
        continue  # key is rate-limited, rotate to next
    elif new_state == KeyState.DISABLED:
        continue  # key is invalid, rotate to next

Handle response auto-dispatching

pool.handle_response(key, status_code, headers, body) introspects the HTTP response and automatically:

Status Action
2xx Marks success — clears errors, resets failure count
429, 413, or "rate_limit_exceeded" in body Marks cooldown, reads Retry-After header
401, 403 Permanently disables the key
5xx Places on cooldown (transient)

Returns KeyState so you can branch on the result.

Load keys from Doppler

import os
from open_keypool import KeyPool

DOPPLER_TOKEN = os.getenv("DOPPLER_TOKEN", "dp.st.YOUR_SERVICE_TOKEN")

pool = KeyPool.from_doppler(
    token=DOPPLER_TOKEN,
    project="refactor-ai",
    config="dev",
    key_prefix="GROQ_",
    strategy="round_robin",
)

# Every key's state, error history, and cooldown — safely masked
for masked_key, info in pool.status().items():
    print(f"{masked_key}  state={info['state']}  "
          f"http={info.get('last_status_code')}  "
          f"err=[{info.get('last_error_code')}]  "
          f"failures={info['failure_count']}")

Load keys from .env file

from open_keypool import KeyPool

# .env contains:
#   TSN_GROQ_KEY=sk-aaa
#   BACKUP_GROQ_KEY=sk-bbb
#   OTHER_SECRET=sk-ccc

pool = KeyPool.from_env(suffix="GROQ_KEY")
# Picks TSN_GROQ_KEY and BACKUP_GROQ_KEY (ends with "GROQ_KEY")

Load keys from JSON file

{
    "TSN_GROQ_KEY": "sk-aaa",
    "BACKUP_GROQ_KEY": "sk-bbb",
    "OTHER_SECRET": "sk-ccc"
}
from open_keypool import KeyPool

pool = KeyPool.from_json("keys.json", suffix="GROQ_KEY")
# Picks TSN_GROQ_KEY and BACKUP_GROQ_KEY (ends with "GROQ_KEY")

Constructor parameters

Parameter Type Default Description
keys list[str] required Initial API key strings (non-empty).
max_retries int 3 Max retry count reference for the caller's loop.
cooldown_seconds int 60 How long a rate-limited key stays in cooldown.
strategy str "round_robin" Rotation strategy: "round_robin" or "lru".

Doppler caching

KeyPool.from_doppler() uses an in-memory TTL cache with a 1-hour expiration. On the first call within a process, keys are fetched from Doppler and cached. Subsequent calls within the same hour serve keys from memory without touching the network. After one hour (if the process is still running), the cache entry expires and the next call fetches fresh keys automatically. The cache is never persisted across process restarts — every fresh process starts with an empty cache.

Pass force_refresh=True to bypass the cache and re-fetch immediately (useful after rotating keys in Doppler when you don't want to wait out the TTL).

Full API reference

docs/index.html — self-contained HTML page with quickstart + class/method documentation generated from docstrings.

Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

open_keypool-0.2.1.tar.gz (62.2 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

open_keypool-0.2.1-py3-none-any.whl (13.3 kB view details)

Uploaded Python 3

File details

Details for the file open_keypool-0.2.1.tar.gz.

File metadata

  • Download URL: open_keypool-0.2.1.tar.gz
  • Upload date:
  • Size: 62.2 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.13

File hashes

Hashes for open_keypool-0.2.1.tar.gz
Algorithm Hash digest
SHA256 d7d78d73b37cc67bc1dc5a23d72e87c2ce365069933d5a214ab16d4c7c497617
MD5 dc0878ddade9b4b292959649b7d56cf4
BLAKE2b-256 1b3273a6c3e2022611a29d450fc1a858be30e22e5e8f06800feacf9d7a846a9f

See more details on using hashes here.

File details

Details for the file open_keypool-0.2.1-py3-none-any.whl.

File metadata

  • Download URL: open_keypool-0.2.1-py3-none-any.whl
  • Upload date:
  • Size: 13.3 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/7.0.0 CPython/3.13.13

File hashes

Hashes for open_keypool-0.2.1-py3-none-any.whl
Algorithm Hash digest
SHA256 7ebd14c7118eb237d19f2aceccb2f876cfc8c8497744e65e46cf1efdf51a35a8
MD5 52bb0e26ebc166bc1bec7c7f89156aca
BLAKE2b-256 74e6481f1b97196712efa573a69be4ebf39b921b1fac0e7877ac7f4a2a4a4042

See more details on using hashes here.

Release history Release notifications | RSS feed

This release

0.2.1 This release

2 files

0.2.0

2 files

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Sentry Error logging StatusPage Status page