Skip to main content

Make API requests using free-tier quota across multiple keys automatically

Project description

free_calls

Make API requests using free-tier quota across multiple keys automatically.

free_calls automatically rotates through multiple API keys when quotas are exhausted, allowing you to maximize your free-tier usage across services.

Installation

pip install free_calls

Or install from source:

git clone https://github.com/MuOssama/free_calls.git
cd free_calls
pip install -e .

Quick Start

1. Set up environment variables

# Single key
export OPENAI_API_KEY="sk-key1"

# Multiple keys (comma-separated)
export OPENAI_API_KEY="sk-key1,sk-key2,sk-key3"

2. Use in your code

from free_calls import FreeCallsManager

# Initialize manager
manager = FreeCallsManager(env_prefix="OPENAI_API_KEY")

# Define your API function (key must be first parameter)
def call_openai_api(api_key, prompt):
    import openai
    openai.api_key = api_key
    response = openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}]
    )
    return response

# Call with automatic rotation
try:
    result = manager.call_with_rotation(
        call_openai_api,
        "Hello, world!",
        quota_error_types=(openai.error.RateLimitError,)
    )
    print(result)
except Exception as e:
    print(f"All keys exhausted: {e}")

Features

Automatic key rotation - Seamlessly switch to next key when quota is exhausted
Runtime status tracking - See which keys are working and which have failed
Multiple API support - Works with any API service
Configurable error types - Define which exceptions trigger rotation
Simple integration - Minimal code changes required

How it Works

  1. Loads all API keys from environment variable
  2. Tries first available key
  3. If quota error occurs, marks key as failed and tries next key
  4. Failed keys are moved to the end of the list
  5. If all keys fail, raises NoValidAPIKeyError

API Reference

FreeCallsManager(env_prefix, separator=",")

Initialize the manager with API keys from environment.

Parameters:

  • env_prefix (str): Environment variable name containing API keys
  • separator (str): Character separating multiple keys (default: ",")

call_with_rotation(api_function, *args, quota_error_types=None, **kwargs)

Call an API function with automatic key rotation on quota errors.

Parameters:

  • api_function (Callable): Function to call (must accept API key as first parameter)
  • quota_error_types (tuple): Exception types indicating quota exhaustion
  • *args, **kwargs: Additional arguments passed to the API function

Returns: Result from the API function

get_ordered_keys()

Get runtime list of all API keys ordered by status.

Returns: List of dicts with:

  • key (str): Masked API key (e.g., "sk-1...xyz4")
  • status (str): Either "active" or "failed"

Example:

keys = manager.get_ordered_keys()
for item in keys:
    print(f"{item['key']}: {item['status']}")

# Output:
# sk-2...def5: active   <- working keys first
# sk-3...ghi6: active
# sk-1...abc4: failed   <- failed keys last

reset()

Reset all failed keys to try them again.

get_current_key()

Get the current active API key (returns None if all failed).

Examples

OpenAI API

from free_calls import FreeCallsManager
import openai

manager = FreeCallsManager("OPENAI_API_KEY")

def chat_completion(api_key, prompt):
    openai.api_key = api_key
    return openai.ChatCompletion.create(
        model="gpt-3.5-turbo",
        messages=[{"role": "user", "content": prompt}]
    )

result = manager.call_with_rotation(
    chat_completion,
    "What is Python?",
    quota_error_types=(openai.error.RateLimitError,)
)

Anthropic Claude API

from free_calls import FreeCallsManager
import anthropic

manager = FreeCallsManager("ANTHROPIC_API_KEY")

def claude_message(api_key, prompt):
    client = anthropic.Anthropic(api_key=api_key)
    return client.messages.create(
        model="claude-3-sonnet-20240229",
        max_tokens=1024,
        messages=[{"role": "user", "content": prompt}]
    )

result = manager.call_with_rotation(
    claude_message,
    "Hello!",
    quota_error_types=(anthropic.RateLimitError,)
)

Custom API

from free_calls import FreeCallsManager
import requests

manager = FreeCallsManager("MY_API_KEY")

def my_api_call(api_key, endpoint, data):
    response = requests.post(
        endpoint,
        headers={"Authorization": f"Bearer {api_key}"},
        json=data
    )
    if response.status_code == 429:  # Rate limit
        raise Exception("Rate limited")
    return response.json()

result = manager.call_with_rotation(
    my_api_call,
    "https://api.example.com/endpoint",
    {"query": "test"},
    quota_error_types=(Exception,)
)

License

MIT License - see LICENSE file for details

Author

Mustapha Ossama - MuOssama

Contributing

Contributions are welcome! Please feel free to submit a Pull Request.

Support

If you encounter any issues or have questions, please file an issue on the GitHub issue tracker.

Project details


Download files

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

Source Distribution

free_calls-0.1.0.tar.gz (6.4 kB view details)

Uploaded Source

Built Distribution

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

free_calls-0.1.0-py3-none-any.whl (4.2 kB view details)

Uploaded Python 3

File details

Details for the file free_calls-0.1.0.tar.gz.

File metadata

  • Download URL: free_calls-0.1.0.tar.gz
  • Upload date:
  • Size: 6.4 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for free_calls-0.1.0.tar.gz
Algorithm Hash digest
SHA256 2d257f2b22fb4862b778f83204ee60591ccc4e9b9e912f98df4200b4ccf3b581
MD5 d2ecd886868682e975c9b89570f7f706
BLAKE2b-256 d7b095874fc45f7baa1225d14d827554be5fdb05b1fe06ad2dc9251c7d428adf

See more details on using hashes here.

File details

Details for the file free_calls-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: free_calls-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 4.2 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.11.2

File hashes

Hashes for free_calls-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 aa14308c9f73273ca7d669f4bf8f8bd830f27adb0cc9c9cd9f7b1ac02bba7553
MD5 4912b9729c71ce3356416e8d3fe943fe
BLAKE2b-256 c4bc96c883c5bede25c03aa01ac12c18c920fa0c9b65e241ee046182a0fe7cda

See more details on using hashes here.

Supported by

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