Skip to main content

Python SDK for Flagpool feature flags

Project description

Flagpool SDK for Python

Official Python SDK for Flagpool - the modern feature flag platform for teams who want control without complexity.

Installation

pip install flagpool-sdk

Quick Start

from flagpool_sdk import FlagpoolClient

client = FlagpoolClient(
    project_id='your-project-uuid',    # Get from Flagpool dashboard
    api_key='fp_production_xxx',       # Environment-specific API key
    decryption_key='fp_dec_xxx',       # For CDN URL hash & target lists
    context={
        'userId': 'user-123',
        'email': 'alice@example.com',
        'plan': 'pro',
        'country': 'US'
    }
)

client.init()

# Boolean flag
if client.is_enabled('new-dashboard'):
    show_new_dashboard()

# String flag (A/B test)
button_color = client.get_value('cta-button-color')
# 'blue' | 'green' | 'orange'

# Number flag
max_upload = client.get_value('max-upload-size-mb')
# 10 | 100 | 1000

# JSON flag
config = client.get_value('checkout-config')
# { 'showCoupons': True, 'maxItems': 50, ... }

# Clean up when done
client.close()

Features

  • Local evaluation - No server roundtrip per flag check
  • Deterministic rollouts - Same user always gets same variation
  • Multiple flag types - Boolean, string, number, JSON (dict)
  • Advanced targeting - 8 operators including target lists
  • Real-time updates - Automatic polling for flag changes
  • Offline support - Works with cached flags when offline
  • Minimal dependencies - Only requires requests

Configuration

client = FlagpoolClient(
    # Required
    project_id='your-project-uuid',     # Project ID from dashboard
    api_key='fp_production_xxx',        # Environment-specific API key
    decryption_key='fp_dec_xxx',        # For CDN URL hash & target list decryption

    # Optional
    context={                           # User context for targeting
        'userId': 'user-123',
        'email': 'user@example.com',
        'plan': 'pro',
        # Add any attributes for targeting
    },
    polling_interval=30,                # Auto-refresh interval (seconds), default: 30
    url_override=None,                  # Complete URL override (for self-hosted/testing)
)

API Reference

Methods

Method Description
init() Initialize client and fetch flags (required before evaluation)
is_enabled(key) Check if a boolean flag is enabled
get_value(key) Get flag value (any type)
get_variation(key) Alias for get_value
get_all_flags() Get all evaluated flag values as dict
update_context(ctx) Update user context and re-evaluate flags
on_change(callback) Subscribe to flag value changes
close() Clean up resources (stop polling)

Flag Types

Boolean Flags

if client.is_enabled('feature-flag'):
    # Feature is enabled for this user
    pass

String Flags

Perfect for A/B tests and feature variants:

variant = client.get_value('button-color')
# Returns: 'blue' | 'green' | 'orange'

Number Flags

Great for limits, thresholds, and configurations:

limit = client.get_value('rate-limit')
# Returns: 100 | 1000 | 10000

JSON Flags (dict)

For complex configurations:

config = client.get_value('checkout-config')
# Returns: { 'showCoupons': True, 'maxItems': 50, ... }

Targeting Rules

Flagpool supports powerful targeting with 8 operators:

Operator Description Example
eq Equals plan == "enterprise"
neq Not equals plan != "free"
in In list country in ["US", "CA"]
nin Not in list country not in ["CN", "RU"]
contains String contains email contains "@company.com"
startsWith String starts with userId startsWith "admin-"
inTargetList In target list userId in beta-testers
notInTargetList Not in target list userId not in blocked-users

Dynamic Context Updates

Update user context on the fly - flags re-evaluate automatically:

client = FlagpoolClient(
    api_key='fp_prod_xxx',
    environment='production',
    context={'userId': 'user-1', 'plan': 'free'}
)

client.init()

# User on free plan
print(client.get_value('max-upload-size-mb'))  # 10

# User upgrades to pro
client.update_context({'plan': 'pro'})

# Instantly gets pro limits
print(client.get_value('max-upload-size-mb'))  # 100

Real-time Updates

Flags automatically refresh in the background:

client = FlagpoolClient(
    api_key='fp_prod_xxx',
    environment='production',
    context={'userId': 'user-1'},
    polling_interval=30  # Refresh every 30 seconds
)

client.init()

# Listen for flag changes
def on_flag_change(flag_key, new_value):
    print(f'Flag {flag_key} changed to: {new_value}')
    
    # React to changes
    if flag_key == 'maintenance-mode' and new_value:
        show_maintenance_banner()

client.on_change(on_flag_change)

Framework Examples

Django

# settings.py
FLAGPOOL_API_KEY = 'fp_production_xxx'

# flags.py
from flagpool_sdk import FlagpoolClient
from django.conf import settings

_client = None

def get_flagpool():
    global _client
    if _client is None:
        _client = FlagpoolClient(
            api_key=settings.FLAGPOOL_API_KEY,
            environment='production',
        )
        _client.init()
    return _client

# views.py
from .flags import get_flagpool

def my_view(request):
    flagpool = get_flagpool()
    flagpool.update_context({'userId': request.user.id})
    
    if flagpool.is_enabled('new-checkout'):
        return render(request, 'new_checkout.html')
    return render(request, 'checkout.html')

Flask

from flask import Flask, g
from flagpool_sdk import FlagpoolClient

app = Flask(__name__)

flagpool = FlagpoolClient(
    api_key='fp_production_xxx',
    environment='production',
)
flagpool.init()

@app.before_request
def set_user_context():
    if hasattr(g, 'user'):
        flagpool.update_context({'userId': g.user.id})

@app.route('/dashboard')
def dashboard():
    if flagpool.is_enabled('new-dashboard'):
        return render_template('new_dashboard.html')
    return render_template('dashboard.html')

FastAPI

from fastapi import FastAPI, Depends
from flagpool_sdk import FlagpoolClient

app = FastAPI()

flagpool = FlagpoolClient(
    api_key='fp_production_xxx',
    environment='production',
)

@app.on_event("startup")
async def startup():
    flagpool.init()

@app.on_event("shutdown")
async def shutdown():
    flagpool.close()

@app.get("/api/data")
async def get_data(user_id: str):
    flagpool.update_context({'userId': user_id})
    
    if flagpool.is_enabled('new-api-response'):
        return {"version": "v2", "data": new_data}
    return {"version": "v1", "data": legacy_data}

Target List Encryption

By default, target lists (used for inTargetList and notInTargetList operators) are encrypted in SDK exports to protect sensitive user data like emails and user IDs.

Encrypted Target Lists (Default)

If your environment has target list encryption enabled, you must provide a crypto adapter:

from flagpool_sdk import FlagpoolClient, set_crypto_adapter

class MyCryptoAdapter:
    def decrypt(self, ciphertext: str, key: str, iv: str, tag: str) -> str:
        # Implement AES-256-GCM decryption
        # See examples/ for a complete implementation using cryptography library
        return decrypted_text

# Set the adapter before creating the client
set_crypto_adapter(MyCryptoAdapter())

client = FlagpoolClient(
    project_id='your-project-uuid',
    api_key='fp_production_xxx',
    decryption_key='fp_dec_xxx',
    context={'userId': 'user-123'}
)

Error: "Encrypted target lists received but no crypto adapter configured"

If you see this error, it means:

  1. Your environment has target list encryption enabled (the default)
  2. You haven't set up a crypto adapter

Solutions:

  1. Set up a crypto adapter (recommended for production):

    set_crypto_adapter(MyCryptoAdapter())
    
  2. Disable encryption (for development/testing):

    • Go to Flagpool Dashboard → Settings → Environments
    • Toggle off "Target List Encryption" for your environment
    • This will export target lists in plaintext (values will be visible)

Plaintext Target Lists

If you disable target list encryption in the dashboard, no crypto adapter is needed. The SDK will use target lists directly without decryption.

⚠️ Security Note: Disabling encryption exposes target list values (emails, user IDs, etc.) in plaintext in the SDK exports. Only disable for development environments or non-sensitive data.

Analytics (Paid Plans Only)

Track flag evaluation counts to understand usage patterns. Analytics is opt-in, disabled by default, and only available on paid plans.

Enabling Analytics

from flagpool_sdk import FlagpoolClient, AnalyticsConfig

client = FlagpoolClient(
    project_id="your-project-uuid",
    api_key="your-api-key",
    decryption_key="your-decryption-key",
    analytics=AnalyticsConfig(enabled=True),
)
client.init()

Configuration Options

analytics=AnalyticsConfig(
    enabled=True,
    flush_interval=60,        # Flush interval in seconds (min: 30)
    flush_threshold=100,      # Flush after N evaluations
    sample_rate=1.0,          # Sample rate 0.0–1.0
    sync_flush_on_shutdown=False,  # Block on exit until flushed
)
Option Type Default Description
enabled bool False Enable/disable analytics
flush_interval int 60 Flush interval in seconds (minimum: 30)
flush_threshold int 100 Flush after N evaluations
sample_rate float 1.0 Sample rate (0.0–1.0)
sync_flush_on_shutdown bool False Flush synchronously on process exit

How It Works

  • Evaluation counts are batched in memory
  • Batches are sent asynchronously (fire-and-forget)
  • Analytics never blocks flag evaluation
  • Data is aggregated daily in your Flagpool dashboard
  • Note: Data is silently discarded for free plan projects

Serverless / Short-Lived Processes

For AWS Lambda or similar short-lived environments, lower the threshold and enable sync flush:

analytics=AnalyticsConfig(
    enabled=True,
    flush_threshold=10,
    sync_flush_on_shutdown=True,
)

Debugging Analytics

# Get current analytics state
state = client.get_analytics_state()
print(state.buffer)         # {'my-flag': 5}
print(state.buffer_size)    # 5
print(state.total_flushes)  # 2

# Get all flags with evaluation status
flags = client.get_all_flags_with_state()
# {'my-flag': {'value': True, 'evaluated': True}, ...}

# Manually flush analytics buffer
client.flush_analytics()

Documentation

For complete documentation, guides, and best practices, visit:

📚 flagpool.io/docs

Support

License

MIT © Flagpool

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

flagpool_sdk-0.3.1.tar.gz (27.9 kB view details)

Uploaded Source

Built Distribution

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

flagpool_sdk-0.3.1-py3-none-any.whl (17.5 kB view details)

Uploaded Python 3

File details

Details for the file flagpool_sdk-0.3.1.tar.gz.

File metadata

  • Download URL: flagpool_sdk-0.3.1.tar.gz
  • Upload date:
  • Size: 27.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for flagpool_sdk-0.3.1.tar.gz
Algorithm Hash digest
SHA256 29e82fcb1c2dd735be9b8454e904d5781a92bdfdd3c1abb957c0dd1b9e0cbd18
MD5 592bb92a871f85fcd2b70ec2d19dc09c
BLAKE2b-256 c601c4c86f13e6e245948808a89f8c0b0eb7081e4779b5e6f59ac0fff00e2791

See more details on using hashes here.

File details

Details for the file flagpool_sdk-0.3.1-py3-none-any.whl.

File metadata

  • Download URL: flagpool_sdk-0.3.1-py3-none-any.whl
  • Upload date:
  • Size: 17.5 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.1.0 CPython/3.13.7

File hashes

Hashes for flagpool_sdk-0.3.1-py3-none-any.whl
Algorithm Hash digest
SHA256 f47d7983f8d61f26d1a8dfe29eb063360a2f26142fb33fffeea966e5262790d4
MD5 0d910fa24c1ccbed472c278001674d02
BLAKE2b-256 35b049bf1e1010f99e2f84cc7e3953f6b94a28d157063d8dc56aacfd62f21327

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