API Keys System
API documentation for API key authentication system
1. Create API Key
- URL:
/api/api-keys
- Method:
POST
- Description: Creates a new API key for programmatic API access. The key is hashed for storage and the original key is only returned once.
- Request Body:
{ "name": "string", "environment": "dev|live" }
- Response:
- Success:
201 Created
{ "id": "string", "name": "string", "environment": "dev|live", "createdAt": "string", "isActive": true, "redactedKey": "sk-dev-abc...z789", "totalUsageCount": 0, "key": "sk-dev-{publicId}-{encryptedData}" }
- Error:
400 Bad Request
{ "message": "Invalid input", "errors": ["name is required and must be a non-empty string"] }
- Error:
401 Unauthorized
{ "message": "Authentication required" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Error details (only in development mode)" }
- Success:
2. List API Keys
- URL:
/api/api-keys
- Method:
GET
- Description: Retrieves all API keys for an organization. Returns redacted keys and usage statistics.
- Response:
- Success:
200 OK
{ "message": "API keys retrieved successfully", "data": { "apiKeys": [ { "id": "string", "name": "string", "environment": "dev|live", "createdAt": "string", "lastUsedAt": "string", "isActive": true, "redactedKey": "sk-dev-abcdef1234...xyz789", "totalUsageCount": 42 } ], "total": 5, "active": 3, "inactive": 2 } }
- Error:
400 Bad Request
{ "message": "Organization ID is required" }
- Error:
401 Unauthorized
{ "message": "Authentication required" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Error details (only in development mode)" }
- Success:
3. Get API Key
- URL:
/api/api-keys/:id
- Method:
GET
- Description: Retrieves details of a specific API key, including usage statistics and redacted key.
- Response:
- Success:
200 OK
{ "id": "string", "name": "string", "environment": "dev|live", "createdAt": "string", "lastUsedAt": "string", "isActive": true, "redactedKey": "sk-dev-abcdef1234...xyz789", "totalUsageCount": 42 }
- Error:
400 Bad Request
{ "message": "API key ID is required" }
- Error:
401 Unauthorized
{ "message": "Authentication required" }
- Error:
404 Not Found
{ "message": "API key not found" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Error details (only in development mode)" }
- Success:
4. Update API Key
- URL:
/api/api-keys/:id
- Method:
PUT
- Description: Updates an existing API key's metadata. The actual key cannot be modified.
- Request Body:
{ "name": "string (optional)", "isActive": true|false (optional) }
- Response:
- Success:
200 OK
{ "id": "string", "name": "string", "environment": "dev|live", "createdAt": "string", "lastUsedAt": "string", "isActive": true, "redactedKey": "sk-dev-abcdef1234...xyz789", "totalUsageCount": 42 }
- Error:
400 Bad Request
{ "message": "No updates provided" }
- Error:
401 Unauthorized
{ "message": "Authentication required" }
- Error:
404 Not Found
{ "message": "API key not found" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Error details (only in development mode)" }
- Success:
5. Delete API Key
- URL:
/api/api-keys/:id
- Method:
DELETE
- Description: Deletes an API key permanently.
- Response:
- Success:
200 OK
{ "message": "API key deleted successfully" }
- Error:
400 Bad Request
{ "message": "API key ID is required" }
- Error:
401 Unauthorized
{ "message": "Authentication required" }
- Error:
404 Not Found
{ "message": "API key not found" }
- Error:
500 Internal Server Error
{ "message": "Internal server error", "error": "Error details (only in development mode)" }
- Success:
API Key Format
sk-{environment}-{publicId}-{encryptedData}
sk
: Prefix indicating "secret key"environment
: Either "dev" or "live"publicId
: UUID for uniquenessencryptedData
: AES-256-CBC encrypted JSON containing userId and orgId
Display Format
sk-{env}-{first10}...{last4}
This redacted format is used for displaying API keys in the UI and logs, providing a safe way to reference keys without exposing sensitive information.
Security Measures
-
Storage Security:
- API keys are hashed using SHA-256 before storage
- Only the hash is stored in the database
- Original key is never stored, only returned once at creation
- Redacted version stored for safe display
- Usage statistics stored in hourly buckets
-
Validation Process:
- Incoming key is hashed for O(1) database lookup
- Hash verification provides first layer of security
- Encrypted data is verified as second layer
- Usage statistics are updated
- User/org data is only decrypted after hash verification
-
Usage Tracking:
- Total lifetime usage count per key
- Hourly usage statistics in format: YYYY-MM-DD-HH
- Last used timestamp for monitoring
- All usage data stored in the same document as the key
- Efficient updates using single database operation
-
Performance Optimization:
- Direct hash lookup instead of collection scan
- Minimal decryption operations
- Efficient database indexing on the hash field
- Optimized usage statistics storage
Authentication
To use an API key for authentication:
- Include the complete API key in the
Authorization
header - Do NOT prefix with "Bearer" (Bearer tokens are for JWT authentication)
- Example:
Authorization: sk-dev-abc123-xyz789...
- The API key automatically sets the organization context
Security Best Practices
-
Key Storage:
- Never log or store the full API key
- Store only the hash in the database
- Use environment variables for encryption keys
- Store redacted version for display purposes
-
Key Management:
- Create separate keys for different environments
- Regularly rotate keys
- Monitor usage patterns through statistics
- Track last used timestamp
- Disable unused keys instead of deleting when possible
-
Access Control:
- Keys are organization-specific
- Embedded user/org data prevents key sharing
- Double verification through hash and encrypted data
- Environment separation prevents key misuse
-
Usage Monitoring:
- Track usage patterns for anomaly detection
- Monitor hourly usage for rate limiting
- Review total usage counts for key rotation decisions
- Use redacted keys in logs and alerts