Docs / API keys
API keys
Create and rotate API keys on a schedule to minimize risk. Restrict scope and access by project where possible, and maintain comprehensive monitoring of usage patterns.
API key management is critical for maintaining secure access to Evaligo services. Proper key lifecycle management, including regular rotation, scope restriction, and usage monitoring, helps organizations maintain security while enabling developer productivity.
Use environment-specific keys to avoid cross-environment leakage and simplify incident response. Clear ownership and documentation of API keys enables rapid response during security events and supports operational transparency.

Key Creation and Management
Follow security best practices when creating API keys. Use descriptive names, set appropriate scopes, and establish clear ownership for each key to enable effective management and incident response.
- 1
Create scoped keys Limit API key permissions to the minimum required for the specific use case.
- 2
Set expiration dates Configure automatic expiration to enforce regular rotation cycles.
- 3
Document ownership Assign clear ownership and contact information for each API key.
- 4
Environment separation Use separate keys for development, staging, and production environments.
from evaligo import Client
admin_client = Client(api_key="admin-key")
# Create environment-specific API key
api_key = admin_client.api_keys.create(
name="production-chatbot-service",
description="Production API key for customer support chatbot",
scopes=["experiments.read", "traces.write", "datasets.read"],
environment="production",
project_ids=["chatbot-prod"],
expires_at="2024-12-31T00:00:00Z",
metadata={
"owner": "platform-team",
"service": "chatbot",
"contact": "platform@company.com"
}
)
print(f"Created API key: {api_key.id}")
print(f"Secret (store securely): {api_key.secret}")
# Set up automatic rotation
rotation_policy = admin_client.api_keys.set_rotation_policy(
key_id=api_key.id,
rotation_interval_days=90,
advance_notification_days=14,
notification_channels=["email", "slack"]
)
Secret Storage: API key secrets are only shown once during creation. Store them securely in a password manager or secrets management system immediately.
Scope and Permission Management
Restrict scope and access by project where possible. Fine-grained permissions help limit the blast radius of compromised keys and support the principle of least privilege.

Define permissions based on the specific needs of each service or integration. Avoid overly broad permissions that could enable unintended access to sensitive data or operations.
# Read-only access for monitoring service
monitoring_key = admin_client.api_keys.create(
name="monitoring-dashboard",
scopes=[
"experiments.read",
"traces.read",
"datasets.read",
"analytics.read"
],
project_ids=["all"] # Can read from all projects
)
# Limited write access for CI/CD
cicd_key = admin_client.api_keys.create(
name="ci-cd-pipeline",
scopes=[
"experiments.write",
"traces.write",
"datasets.write"
],
project_ids=["staging-env"], # Only staging environment
ip_whitelist=["10.0.1.0/24"] # Restrict to CI/CD network
)
# Service-specific permissions
chatbot_key = admin_client.api_keys.create(
name="chatbot-service",
scopes=[
"traces.write", # Log conversation traces
"experiments.read" # Read prompt configurations
],
project_ids=["chatbot-prod"],
rate_limit_per_minute=1000
)
Usage Monitoring
Monitor usage and revoke keys promptly when suspicious activity is detected. Comprehensive monitoring helps identify potential security issues and supports capacity planning for API services.
Anomaly Detection: Set up alerts for unusual usage patterns such as requests from new IP addresses, spikes in request volume, or access to unexpected resources.

# Get usage statistics for all keys
usage_stats = admin_client.api_keys.usage_stats(
time_range="last_30_days",
group_by=["key_id", "ip_address", "user_agent"]
)
# Identify suspicious activity
for key_stats in usage_stats:
if key_stats.unique_ip_count > 10:
print(f"Alert: Key {key_stats.key_name} used from {key_stats.unique_ip_count} IPs")
if key_stats.requests_per_hour > key_stats.normal_rate * 3:
print(f"Alert: Unusual spike in usage for {key_stats.key_name}")
# Set up automated monitoring
admin_client.api_keys.create_monitor(
name="API Key Anomaly Detection",
conditions=[
{"metric": "unique_ip_count", "threshold": 5, "window": "1h"},
{"metric": "request_rate", "threshold": "3x_baseline", "window": "5m"},
{"metric": "error_rate", "threshold": 0.1, "window": "15m"}
],
actions=[
{"type": "alert", "channels": ["security-team"]},
{"type": "temporary_suspend", "duration": "1h"}
]
)
Rotation and Lifecycle
Document ownership and rotation procedures for operational clarity. Regular rotation reduces the impact of compromised keys and supports compliance with security policies.
Video

Implement automated rotation where possible, with appropriate advance notification to service owners. Manual rotation procedures should be well-documented and tested regularly to ensure smooth operations during incidents.
Rotation Strategy: Plan key rotation during low-traffic periods and have rollback procedures ready in case of issues. Test rotation procedures regularly in non-production environments.
# Implement graceful key rotation
def rotate_api_key(key_id):
# Create new key with same permissions
old_key = admin_client.api_keys.get(key_id)
new_key = admin_client.api_keys.create(
name=f"{old_key.name}-rotated",
scopes=old_key.scopes,
project_ids=old_key.project_ids,
expires_at=old_key.expires_at
)
# Notify service owners
notification = admin_client.notifications.send(
recipients=old_key.metadata.get("contact", []),
subject=f"API Key Rotation Required: {old_key.name}",
message=f"""
Your API key '{old_key.name}' will be rotated.
New Key ID: {new_key.id}
Old Key Expires: {old_key.expires_at}
Please update your services with the new key.
"""
)
# Schedule old key deactivation
admin_client.api_keys.schedule_deactivation(
key_id=old_key.id,
deactivate_at=datetime.utcnow() + timedelta(days=30)
)
return new_key
# Schedule regular rotation
admin_client.schedules.create(
name="quarterly-key-rotation",
frequency="quarterly",
action="rotate_keys",
filters={"environment": "production"}
)