Skip to main content

Overview

Codex-LB supports API key authentication to control access to your load balancer. Each key can have:
  • Model restrictions - Limit which models can be accessed
  • Rate limits - Token, request, and cost limits per day/week/month
  • Expiration dates - Automatic key deactivation
  • Usage tracking - Monitor consumption per key
API key authentication is disabled by default. Enable it via Settings → API Key Auth Enabled.

Creating API Keys

Via Dashboard

  1. Navigate to SettingsAPI Keys
  2. Click Create API Key
  3. Configure:
    • Name: Descriptive label (e.g., “Production App”)
    • Allowed Models: Leave empty for all models, or select specific models
    • Expiration: Optional expiration date
    • Limits: Add rate limits (see Rate Limits)
  4. Click Create
  5. Copy the key immediately - it won’t be shown again!

Via API

Response:
The key field contains the full API key and is only returned once on creation. Store it securely!

Key Format

API keys follow this format:
Example: sk-clb-a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6q7r8s9t0u1v2w3x4y5z6 Storage: Only the SHA-256 hash is stored in the database (from app/modules/api_keys/service.py:512-513):

Using API Keys

Authentication Header

Include the key in the Authorization header:

Scope

API key authentication applies to:
  • /v1/* (OpenAI-compatible endpoints)
  • /backend-api/codex/* (ChatGPT-compatible endpoints)
  • /backend-api/transcribe (Transcription endpoint)
Excluded:
  • /api/* (Dashboard API - uses session auth)
  • /api/codex/usage (Uses bearer caller identity, not API keys)

Model Restrictions

Configuring Allowed Models

When creating or updating a key:
  • Empty/null: All models allowed
  • Specific list: Only listed models allowed

Enforcement

Model restrictions are enforced in the proxy service layer:
Error response:
HTTP Status: 403 Forbidden

Model List Filtering

GET /v1/models automatically filters based on the authenticated key:
Returns only models in the key’s allowed_models list.

Fixed-Model Endpoints

For endpoints with implicit models (e.g., transcription):
Transcription endpoints use model gpt-4o-transcribe for restriction checks.

Rate Limits

Limit Types

Codex-LB supports four limit types:

Limit Windows

Creating Limits

Example: Daily token limit
Example: Weekly cost limit
Example: Model-specific limit
Combine global and model-specific limits for granular control. Example: 10M tokens/day globally, but only 1M tokens/day for expensive models.

Limit Enforcement

Limits are enforced using a reservation system to prevent races:
Reservation flow:
  1. Before request: Reserve estimated usage (8,192 tokens for token limits, $2 for cost limits)
  2. Process request: Forward to upstream API
  3. After response: Adjust reservation to actual usage
  4. On error: Release reservation
From app/modules/api_keys/service.py:584-601:
Reservations prevent over-limit requests from starting, even under high concurrency. Actual usage is settled after the response, refunding unused quota.

Limit Applicability

From openspec/specs/api-keys/spec.md:223-232:
  • model_filter=null: Applies to all requests (global limit)
  • model_filter="gpt-4o": Applies only to gpt-4o requests
  • Model-less endpoints (e.g., /v1/models): Only global limits apply
Example scenario: Key has two limits:
  1. total_tokens=1M/day, model_filter=null (global)
  2. total_tokens=100K/day, model_filter="gpt-4o" (model-specific)
Request for gpt-4o: Both limits enforced Request for gpt-4o-mini: Only global limit enforced

Exceeding Limits

Error response:
HTTP Status: 429 Too Many Requests Header: Retry-After: 3600 (seconds until reset)

Automatic Reset

Limits reset using lazy evaluation:
Reset timing:
Resets happen on next key validation after reset_at timestamp passes.

Managing API Keys

Listing Keys

Response:
The full key is never returned after creation. Only key_prefix (first 15 characters) is shown.

Updating Keys

Updatable fields:
  • name
  • allowed_models
  • expires_at
  • is_active
  • limits
Example: Add a new limit
State preservation: From openspec/specs/api-keys/spec.md:259-265:
When updating API key limits, the system SHALL preserve existing usage state (current_value, reset_at) for unchanged limit rules. Limit comparison key is (limit_type, limit_window, model_filter).
Existing limits retain their counters; only new or modified limits reset.

Disabling Keys

Disabled keys:
  • Return 401 Unauthorized on use
  • Remain in database for audit trail
  • Can be re-enabled by setting is_active: true

Regenerating Keys

If a key is compromised:
Response: New key with same ID, name, and limits:
Old key immediately stops working.

Deleting Keys

Permanently removes key and all associated limits. HTTP 204 on success.

Usage Tracking

Every API request records usage:
RequestLog association: From openspec/specs/api-keys/spec.md:194-206:
The system SHALL record the api_key_id in the request_logs table for proxy requests authenticated with an API key.
View per-key request history:

Security Best Practices

Key Rotation

  1. Create new key with desired settings
  2. Update applications to use new key
  3. Monitor old key’s last_used_at timestamp
  4. Delete old key after migration complete
Recommended rotation frequency: Every 90 days

Principle of Least Privilege

  • Model restrictions: Limit keys to only required models
  • Rate limits: Set limits matching expected usage + margin
  • Expiration: Use expiration dates for temporary access
Example: Frontend key

Monitoring

Set up alerts for:
  • Keys approaching limits (>80% utilization)
  • Keys with no recent usage (potential leak)
  • Unusual traffic patterns (rapid usage spikes)
  • 429 errors (limit exceeded)

Revoking Compromised Keys

If a key is exposed:
  1. Immediately disable via PATCH with is_active: false
  2. Investigate usage logs for unauthorized activity
  3. Regenerate or create new key
  4. Update legitimate applications
  5. Delete old key after verification
Disabling API key auth while keys exist is dangerous. Keys remain valid but the enforcement check is skipped. Delete all keys before disabling auth.

Global API Key Authentication

Enabling Authentication

API key authentication is controlled via settings:
When enabled:
  • All proxy requests require valid API key
  • Dashboard API still uses session auth
  • Missing or invalid keys return 401 Unauthorized

Disabling Authentication

When disabled:
  • Proxy requests allowed without authentication
  • Existing keys remain in database but aren’t enforced
  • No usage tracking or rate limiting
Leave API key auth disabled during initial setup and testing. Enable it before exposing Codex-LB to external networks.

Troubleshooting

401 Unauthorized

Causes:
  • Missing Authorization header
  • Invalid key format
  • Key deleted or disabled
  • Key expired
Solution: Check key is active, not expired, and header is correctly formatted.

403 Model Not Allowed

Causes:
  • Requested model not in allowed_models
  • Model filter typo
Solution: Update key’s allowed_models or use a different model.

429 Rate Limit Exceeded

Causes:
  • Hit daily/weekly/monthly limit
  • Multiple limits stacked (global + model-specific)
Solution: Wait for reset (check Retry-After header) or increase limits.

Limits Not Resetting

Causes:
  • Reset logic runs on next validation (lazy)
  • Clock drift on server
Solution: Trigger a request with the key to force reset check, or manually adjust reset_at in database.

Technical Reference

Key source files:
  • app/modules/api_keys/service.py - API key business logic
  • app/modules/api_keys/repository.py - Database operations
  • app/modules/api_keys/schemas.py - API schemas
  • app/db/models.py:152-274 - Database models
  • openspec/specs/api-keys/spec.md - Detailed specification