Configuration
The Toggly Python SDK can be configured using TogglyConfig or through framework-specific settings.
User context belongs to each request
Normal boolean evaluation fetches global definitions and evaluates with each request's user context. Pass identity, memberships and claims into that local evaluation; do not mutate a shared application's startup identity for each user. Optional remotely evaluated variants have a separate client-scoped context. Configure that fixed context before startup as shown below. It does not replace the request-local context used by ordinary boolean evaluation.
TogglyConfig Options
from toggly import TogglyConfig
config = TogglyConfig(
# Required
app_key="your-app-key",
# Optional
environment="Production", # Environment name
base_url="https://definitions.toggly.io", # API base URL
refresh_interval=180.0, # Seconds between refreshes
connect_timeout=10.0, # Connection timeout in seconds
request_timeout=30.0, # Request timeout in seconds
enable_usage_tracking=True, # Track feature usage
disable_background_refresh=False, # Disable auto-refresh
use_signed_definitions=False, # Verify signed definitions (ES256)
allowed_key_ids=None, # Optional kid allow-list
enable_live_updates=True, # WebSocket live updates
feature_defaults={}, # Default feature values
debug=False, # Enable debug logging
)
Initial context for remote variants
from toggly import TogglyClient, TogglyConfig
client = TogglyClient(TogglyConfig(
app_key="your-app-key",
enable_variants=True,
identity="user-123", # Stable ID for this variants client.
variant_groups=["beta"], # Memberships used by targeting rules.
variant_claims={"plan": "pro"}, # String rule attributes.
))
client.init() # The first variants request includes the complete context.
AsyncTogglyClient accepts the same configuration; use await client.init().
Django, Flask and FastAPI accept these startup options in their SDK configuration.
They are application-wide defaults, not values to replace for every incoming
request. Keep ordinary local boolean checks request-scoped with EvaluationContext.
Enabling remote variants uses client-wide evaluated flags and variants.
The client copies collections before startup. Empty collections add no targeting values; blank groups and empty claim names/values are omitted. Claims are strings, with whitespace preserved and at most 20 sorted claim names sent. Cached variants and conditional validators must match the complete context.
Configuration Options Reference
| Option | Type | Default | Description |
|---|---|---|---|
app_key | str | Required | Your Toggly application key |
environment | str | "Production" | Environment name (Production, Staging, etc.) |
base_url | str | "https://definitions.toggly.io" | Toggly API base URL |
refresh_interval | float | 180.0 | Seconds between background refreshes |
connect_timeout | float | 10.0 | HTTP connection timeout in seconds |
request_timeout | float | 30.0 | HTTP request timeout in seconds |
enable_usage_tracking | bool | True | Whether to track feature usage |
disable_background_refresh | bool | False | Disable automatic background refresh |
use_signed_definitions | bool | False | Verify cryptographically signed definitions |
allowed_key_ids | list[str] | None | None | Allowed signing key IDs (None = all) |
enable_live_updates | bool | True | WebSocket live updates (toggly[websocket]) |
feature_defaults | dict | {} | Default values for features |
on_error | callable | None | None | Callback for refresh / signature failures |
debug | bool | False | Enable debug logging |
Signed definitions
See Signed definitions for JWKS + ES256 verification. Shared contract: Server-side reliability.
Live updates (WebSockets)
See Live updates. Protocol: WebSocket sync.
Built-in filter inventory
EvaluatorRegistry ships these evaluators:
| Filter name | Purpose |
|---|---|
AlwaysOn / AlwaysOff | Static on / off |
Percentage | Deterministic rollout from identity |
TimeWindow | Time-based availability |
Targeting | Users / groups / default rollout % |
BrowserFamily, BrowserLanguage, Country / CountryFamily, DeviceType, OS / OperatingSystem | HTTP segment filters via request |
UserClaims | Principal claims via claims |
ContextProperty | Entity property filters (fail closed) |
Segment and UserClaims filters need EvaluationContext.claims and
EvaluationContext.request. Map headers with HttpRequestMapper.from_http_headers
(or merge_into) — same country header precedence as Node
fromHttpRequest.
UserClaims never reads HTTP headers; set claims from your auth layer.
Missing context or an unknown filter name fails closed. Matrix:
SDK × filter matrix.
from toggly import EvaluationContext, HttpRequestMapper, RequestContext
base = EvaluationContext(
identity=user_id,
claims={"role": role_from_auth},
)
context = HttpRequestMapper.merge_into(request.headers, base)
# Or set request explicitly:
# context = base.with_request(RequestContext(country="US", user_agent=ua))
if client.is_enabled("MobileCheckout", context):
...
Django / Flask / FastAPI helpers may not auto-map segment headers — wire
HttpRequestMapper (or request=) when you need those filters.
Register custom filters via the evaluator registry (see Advanced Usage).
Framework-Specific Configuration
- Django
- Flask
- FastAPI
# settings.py: read by the toggly_django AppConfig at startup.
import os
TOGGLY = {
"APP_KEY": os.environ.get("TOGGLY_APP_KEY"),
"ENVIRONMENT": "Production",
"BASE_URL": "https://definitions.toggly.io",
"REFRESH_INTERVAL": 180.0,
"CONNECT_TIMEOUT": 10.0,
"REQUEST_TIMEOUT": 30.0,
"ENABLE_USAGE_TRACKING": True,
"DISABLE_BACKGROUND_REFRESH": False,
"USE_SIGNED_DEFINITIONS": False,
"FEATURE_DEFAULTS": {},
"DEBUG": False,
# Optional fixed context for a remote-variants client:
"ENABLE_VARIANTS": False,
"IDENTITY": None,
"VARIANT_GROUPS": [],
"VARIANT_CLAIMS": {},
}
enable_live_updates is not a Django settings key; it defaults to True on
TogglyConfig. Override by constructing a client and wiring it yourself — see
Live updates.
# config.py or app.py
app.config["TOGGLY_APP_KEY"] = "your-app-key"
app.config["TOGGLY_ENVIRONMENT"] = "Production"
app.config["TOGGLY_REFRESH_INTERVAL"] = 180.0
app.config["TOGGLY_CONNECT_TIMEOUT"] = 10.0
app.config["TOGGLY_REQUEST_TIMEOUT"] = 30.0
app.config["TOGGLY_ENABLE_USAGE_TRACKING"] = True
app.config["TOGGLY_DISABLE_BACKGROUND_REFRESH"] = False
app.config["TOGGLY_USE_SIGNED_DEFINITIONS"] = False
app.config["TOGGLY_FEATURE_DEFAULTS"] = {}
app.config["TOGGLY_DEBUG"] = False
from toggly_fastapi import configure_toggly
configure_toggly(
app_key="your-app-key",
environment="Production",
refresh_interval=180.0,
connect_timeout=10.0,
request_timeout=30.0,
enable_usage_tracking=True,
disable_background_refresh=False,
use_signed_definitions=False,
feature_defaults={},
debug=False,
)
toggly-fastapi requires Python 3.9+ (requires-python = ">=3.9"). The
core toggly package supports 3.8+.
Environment Variables
Read environment variables in your application setup and pass typed values to the SDK:
export TOGGLY_APP_KEY="your-app-key"
export TOGGLY_ENVIRONMENT="Production"
export TOGGLY_BASE_URL="https://definitions.toggly.io"
export TOGGLY_REFRESH_INTERVAL="180"
export TOGGLY_CONNECT_TIMEOUT="10"
export TOGGLY_REQUEST_TIMEOUT="30"
export TOGGLY_ENABLE_USAGE_TRACKING="true"
export TOGGLY_DISABLE_BACKGROUND_REFRESH="false"
export TOGGLY_USE_SIGNED_DEFINITIONS="false"
export TOGGLY_DEBUG="false"
import os
from toggly import TogglyConfig
config = TogglyConfig(
app_key=os.environ.get("TOGGLY_APP_KEY"),
environment=os.environ.get("TOGGLY_ENVIRONMENT", "Production"),
refresh_interval=float(os.environ.get("TOGGLY_REFRESH_INTERVAL", "180")),
enable_usage_tracking=os.environ.get(
"TOGGLY_ENABLE_USAGE_TRACKING", "true"
).lower() == "true",
)
TogglyConfig does not read the process environment itself. Map the options you use, including parsing numbers and booleans. The framework examples read Django/Flask configuration or explicit FastAPI arguments before initialization.
Feature Defaults
You can specify default values for features that will be used when the feature definition is not found or the API is unavailable:
config = TogglyConfig(
app_key="your-app-key",
feature_defaults={
"new-checkout": False, # Disabled by default
"dark-mode": True, # Enabled by default
"api-v2": False, # Disabled by default
}
)
Initialization
Synchronous Client
from toggly import TogglyClient, TogglyConfig
config = TogglyConfig(app_key="your-app-key")
client = TogglyClient(config)
# Initialize the client (fetches feature definitions)
client.init()
# Use the client
if client.is_enabled("my-feature"):
print("Feature enabled!")
# Cleanup when done
client.close()
Async Client
import asyncio
from toggly import AsyncTogglyClient, TogglyConfig
config = TogglyConfig(app_key="your-app-key")
client = AsyncTogglyClient(config)
async def main():
# Initialize the client
await client.init()
# Use the client
if await client.is_enabled("my-feature"):
print("Feature enabled!")
# Cleanup when done
await client.close()
asyncio.run(main())
Context Manager
Both clients support the context manager pattern for automatic cleanup:
# Synchronous
with TogglyClient(config) as client:
client.init()
if client.is_enabled("my-feature"):
print("Feature enabled!")
# Async
async with AsyncTogglyClient(config) as client:
await client.init()
if await client.is_enabled("my-feature"):
print("Feature enabled!")
Global Client
For convenience, you can set a global default client:
from toggly import TogglyClient, TogglyConfig, set_default_client, get_default_client
config = TogglyConfig(app_key="your-app-key")
client = TogglyClient(config)
client.init()
# Set as default
set_default_client(client)
# Later, retrieve from anywhere
client = get_default_client()
if client and client.is_enabled("my-feature"):
print("Feature enabled!")
Framework-owned initialization registers the default client. When supplying a preconfigured Flask client, also call set_default_client(client) once at startup so native decorators use it. Never replace the global client or its identity for each user.