37 - API Key & Playground
Overview
OpenAlgo provides a secure API key management system and an interactive API Playground for testing REST API and WebSocket endpoints. API keys are hashed using Argon2 with pepper for storage and encrypted using Fernet for retrieval.
Architecture Diagram
┌───────────────────────────────────────────────────────────────────────────────┐
│ API Key Architecture │
└───────────────────────────────────────────────────────────────────────────────┘
Generate API Key Request
│
▼
┌───────────────────────────────────────────────────────────────────────────────┐
│ API Key Generation │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ api_key = secrets.token_hex(32) # 64 character hex string │ │
│ │ │ │
│ │ Example: a1b2c3d4e5f6...789012345678901234567890abcdef12345678 │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────────┐
│ Dual Storage Strategy │
│ │
│ ┌──────────────────────────────┐ ┌──────────────────────────────────────┐ │
│ │ Hashed (Argon2 + Pepper) │ │ Encrypted (Fernet) │ │
│ │ For API authentication │ │ For TradingView integration │ │
│ │ │ │ │ │
│ │ hash = argon2.hash( │ │ encrypted = fernet.encrypt( │ │
│ │ api_key + pepper │ │ api_key │ │
│ │ ) │ │ ) │ │
│ │ │ │ │ │
│ │ → Stored in api_key_hash │ │ → Stored in api_key_encrypted │ │
│ └──────────────────────────────┘ └──────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────────┘
│
▼
┌───────────────────────────────────────────────────────────────────────────────┐
│ api_keys Table (SQLite) │
│ │
│ ┌─────────────────────────────────────────────────────────────────────┐ │
│ │ id | user_id | api_key_hash | api_key_encrypted | order_mode │ │
│ │ ───┼─────────┼──────────────┼───────────────────┼─────────────────│ │
│ │ 1 | admin | $argon2id... | gAAAAA... | auto │ │
│ └─────────────────────────────────────────────────────────────────────┘ │
└───────────────────────────────────────────────────────────────────────────────┘API Key Generation
Location: blueprints/apikey.py
Blueprint: api_key_bp, url_prefix="/". It exposes /apikey (GET returns the current key state, POST regenerates the key) and /apikey/mode (POST). Both are guarded by @check_session_validity and neither carries a @limiter.limit decorator.
Key Properties
Length
64 characters (hex)
Entropy
256 bits
Format
Hexadecimal (0-9, a-f)
Generation
secrets.token_hex(32)
API Key Storage
Dual Storage for Different Use Cases
The model is ApiKeys in database/auth_db.py with __tablename__ = 'api_keys'. Its columns are id, user_id (unique), api_key_hash, api_key_encrypted, created_at and order_mode (default 'auto').
order_mode is not written by upsert_api_key(). It falls back to the column default 'auto' on insert and is changed only through update_order_mode().
API Key Verification
Only the SHA-256 cache key and the resolved user_id are cached, never the key itself. upsert_api_key() and update_order_mode() both call invalidate_user_cache(). Order mode is cached separately in order_mode_cache (TTLCache, maxsize 128, TTL 60 seconds).
Order Mode
Auto vs Semi-Auto Mode
auto
Orders execute immediately
Personal trading
semi_auto
Orders require manual approval
Managed accounts
API Playground
Location: blueprints/playground.py
Architecture
Endpoint Categories
categorize_endpoint() matches against the lowercased path and returns one of account, orders, data or utilities. WebSocket entries bypass it: load_bruno_endpoints() assigns them to a fifth bucket, websocket, based on the .bru meta type.
.bru files are read from collections/openalgo/<broker_type>/**/*.bru, where broker_type is IN_stock (the default) or crypto, resolved from the logged in broker's capabilities. collection.bru metadata files are skipped, entries are ordered by the seq value in their meta block and then sorted alphabetically by name inside each category.
API Endpoints
Blueprint: playground, url_prefix="/playground".
/playground/
GET
Legacy URL. Redirects (302) to the React-served /playground page
/playground/api-key
GET
Get user's API key
/playground/collections
GET
Get Postman/Bruno collections
/playground/endpoints
GET
Get structured endpoint list
The playground UI itself is served by the React SPA (blueprints/react_app.py), not by a Jinja template in this blueprint. /playground/api-key, /playground/collections and /playground/endpoints are guarded by @check_session_validity. /playground/ is not.
WebSocket Testing
WebSocket Endpoint Format in Bruno
WebSocket Actions
subscribe
Subscribe to symbols
unsubscribe
Unsubscribe from symbols
API Usage Examples
Using API Key in Requests
Note: Header authentication with
X-API-KEYis accepted only by the bot endpoints (restx_api/telegram_bot.pyandrestx_api/whatsapp_bot.py). The regular/api/v1trading and data endpoints take the key from the request body.
TradingView Integration
Security Considerations
API Key Protection
Storage
Argon2 hash (api_key_hash) plus Fernet encryption (api_key_encrypted)
Transit
HTTPS recommended
Verification
Pepper plus Argon2 PasswordHasher.verify()
Caching
verified_api_key_cache TTL 36000s, invalid_api_key_cache TTL 300s, both keyed by SHA-256 of the key and invalidated on key regeneration
Playground Security
Session authentication required
CSRF protection (exempted for API endpoints)
API key auto-populated from session
No API key logging
Key Files Reference
blueprints/apikey.py
API key CRUD operations
blueprints/playground.py
API testing playground
database/auth_db.py
API key storage/verification
collections/**/*.bru
Bruno endpoint definitions
frontend/src/pages/ApiKey.tsx
React API key page
frontend/src/pages/Playground.tsx
React WebSocket/API playground
Last updated