Skip to main content

Overview

The API Keys API provides endpoints for creating and managing API keys - long-lived authentication credentials for programmatic access. API keys are ideal for scripts, automation, and integrations that need persistent authentication without interactive login.
v2.8.0 adds API key management with secure bcrypt hashing and Kong gateway integration for API key→JWT exchange.

Use Cases

  • CLI Tools: Command-line interfaces and developer tools
  • Scripts & Automation: Cron jobs, shell scripts, automated tasks
  • CI/CD Integration: Build pipelines, deployment automation
  • Third-Party Integrations: External systems that need API access
  • Development & Testing: Local development without SSO

API Key vs Service Principal

  • API Keys
  • Service Principals
User-scoped credentials
  • Tied to a specific user account
  • Inherit user’s permissions
  • Limited to 5 keys per user
  • Expire after configurable period (default: 365 days)
  • Ideal for: CLI tools, scripts, personal automation
curl https://api.yourdomain.com/message \
  -H "X-API-Key: ak_abc123..."

Base URL

https://api.yourdomain.com/api/v1/api-keys

Authentication

All endpoints require user authentication:
  • Authorization: Bearer {token}
  • Users can only manage their own API keys

Endpoints

POST /

Create a new API key for the current user. Creates a cryptographically secure API key with bcrypt hashing. Maximum 5 keys per user - revoke an existing key before creating more. Request Body:
name
string
required
Human-readable name for the API key (e.g., “Production CLI Tool”)
expires_days
integer
default:365
Days until expiration (default: 365 days)
Request Example:
curl -X POST https://api.yourdomain.com/api/v1/api-keys/ \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..." \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production CLI Tool",
    "expires_days": 365
  }'
Response:
{
  "key_id": "key_abc123def456",
  "name": "Production CLI Tool",
  "created": "2025-10-29T10:00:00Z",
  "expires_at": "2026-10-29T10:00:00Z",
  "api_key": "ak_live_abc123def456xyz789...",
  "message": "API key created successfully. Save it securely - it will not be shown again."
}
Save the api_key securely - it will not be shown again! Store it in a password manager or environment variable. The plain-text key is hashed with bcrypt before storage.
Status Codes:
201
Created
API key created successfully
400
Bad Request
Invalid input or exceeded key limit
{
  "error": "validation_error",
  "message": "Maximum 5 API keys allowed per user. Revoke an existing key first."
}
401
Unauthorized
Not authenticated

GET /

List all API keys for the current user. Returns metadata for all keys (name, created, expires, last_used). Does not include the actual API keys. Request Example:
curl https://api.yourdomain.com/api/v1/api-keys/ \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
Response:
[
  {
    "key_id": "key_abc123def456",
    "name": "Production CLI Tool",
    "created": "2025-10-29T10:00:00Z",
    "expires_at": "2026-10-29T10:00:00Z",
    "last_used": "2025-10-29T14:30:00Z"
  },
  {
    "key_id": "key_xyz789",
    "name": "Development Script",
    "created": "2025-09-15T08:00:00Z",
    "expires_at": "2026-09-15T08:00:00Z",
    "last_used": null
  }
]
Status Codes:
200
Success
API keys retrieved successfully
401
Unauthorized
Not authenticated

POST //rotate

Rotate an API key. Generates a new API key while keeping the same key_id. The old key is invalidated immediately. Path Parameters:
key_id
string
required
Unique identifier of the API key to rotate
Request Example:
curl -X POST https://api.yourdomain.com/api/v1/api-keys/key_abc123def456/rotate \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
Response:
{
  "key_id": "key_abc123def456",
  "new_api_key": "ak_live_newkey123...",
  "message": "API key rotated successfully. Update your client configuration."
}
Update your client configuration immediately! The old API key is invalidated and will no longer work. Save the new new_api_key securely.
Status Codes:
200
Success
API key rotated successfully
401
Unauthorized
Not authenticated
404
Not Found
API key not found or not owned by current user
{
  "error": "not_found",
  "message": "API key 'key_abc123def456' not found"
}

DELETE /

Revoke an API key. Permanently deletes the API key. This action cannot be undone. Any clients using this key will immediately lose access. Path Parameters:
key_id
string
required
Unique identifier of the API key to revoke
Request Example:
curl -X DELETE https://api.yourdomain.com/api/v1/api-keys/key_abc123def456 \
  -H "Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9..."
Response: No content (HTTP 204) Status Codes:
204
No Content
API key revoked successfully
401
Unauthorized
Not authenticated
404
Not Found
API key not found

POST /validate

Validate API key and return JWT (internal endpoint for Kong plugin).
Internal Endpoint: This endpoint is called by the Kong API gateway plugin and is not intended for direct client use. It is excluded from the public API schema.
This endpoint validates an API key and issues a JWT for the associated user. It implements the API key→JWT exchange pattern described in ADR-0034. Headers:
X-API-Key
string
required
API key to validate
Request Example:
curl -X POST https://api.yourdomain.com/api/v1/api-keys/validate \
  -H "X-API-Key: ak_live_abc123def456xyz789..."
Response:
{
  "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
  "expires_in": 900,
  "user_id": "user:alice",
  "username": "alice"
}
Status Codes:
200
Success
API key validated, JWT issued
400
Bad Request
Missing X-API-Key header
401
Unauthorized
Invalid or expired API key
500
Internal Server Error
Failed to issue JWT

Using API Keys

1. Create API Key

# Login as user to get JWT
curl -X POST https://api.yourdomain.com/auth/login \
  -d '{"username": "alice", "password": "password123"}'

# Create API key
curl -X POST https://api.yourdomain.com/api/v1/api-keys/ \
  -H "Authorization: Bearer $USER_TOKEN" \
  -d '{"name": "My CLI Tool", "expires_days": 365}'

# Save the api_key from response
export API_KEY="ak_live_abc123def456xyz789..."

2. Use API Key (Direct)

# Make API requests with X-API-Key header
curl https://api.yourdomain.com/message \
  -H "X-API-Key: $API_KEY" \
  -d '{"query": "Hello!"}'

3. Use API Key (via Kong Gateway)

When Kong gateway is configured with the API key plugin:
# Kong validates API key and exchanges for JWT automatically
curl https://api.yourdomain.com/message \
  -H "X-API-Key: $API_KEY" \
  -d '{"query": "Hello!"}'

# Behind the scenes:
# 1. Kong intercepts request
# 2. Calls /api/v1/api-keys/validate with X-API-Key
# 3. Receives JWT token
# 4. Forwards request with Authorization: Bearer <JWT>

4. Environment-Based Configuration

# .env file
API_KEY=ak_live_abc123def456xyz789...

# Python script
import os
import httpx

api_key = os.getenv("API_KEY")
response = httpx.post(
    "https://api.yourdomain.com/message",
    headers={"X-API-Key": api_key},
    json={"query": "Process data"}
)

Security Best Practices

Never hardcode API keys in code
  • Store in environment variables: export API_KEY=ak_live_...
  • Use .env files (add to .gitignore)
  • Use secret managers in production: HashiCorp Vault, AWS Secrets Manager
  • Password managers for personal keys: 1Password, LastPass
Never:
  • Commit API keys to Git
  • Store in plain text files
  • Share via email or chat
  • Embed in client-side code
Rotate keys regularly
  • Quarterly rotation for production keys
  • Immediately after security incidents
  • When team members leave
  • If key may have been exposed
Zero-downtime rotation:
  1. Create new API key
  2. Update client configuration
  3. Test with new key
  4. Revoke old key
Set appropriate expiration periods
  • Short-lived (30-90 days): Development, testing
  • Medium-lived (180-365 days): Production tools, CLI
  • Long-lived (1-2 years): Stable integrations (with rotation)
Monitor expiration and renew before expiry:
# List keys and check expiration
curl https://api.yourdomain.com/api/v1/api-keys/ \
  -H "Authorization: Bearer $TOKEN"
API keys inherit user permissions
  • Create dedicated user accounts for automation
  • Grant minimum required permissions
  • Use service principals for broader access
  • Monitor API key usage in audit logs
5 key limit per user
  • Encourages key hygiene and rotation
  • Prevents accumulation of unused keys
  • Revoke unused keys regularly
Monitor usage:
  • Track last_used timestamp
  • Alert on dormant keys (unused > 30 days)
  • Review keys quarterly
  • Revoke keys for decommissioned tools

Kong Gateway Integration

When using Kong API Gateway with the custom API key plugin:
1

Kong receives request with X-API-Key

Client sends request with X-API-Key header to Kong gateway
2

Kong validates API key

Kong calls /api/v1/api-keys/validate (internal endpoint) with the API key
3

Backend issues JWT

Backend validates API key and returns JWT token if valid
4

Kong forwards with JWT

Kong replaces X-API-Key header with Authorization: Bearer <JWT> and forwards to backend
5

Backend processes request

Backend receives JWT-authenticated request and processes normally
This pattern provides:
  • ✅ Long-lived credentials (API keys) for clients
  • ✅ Short-lived tokens (JWT) for internal services
  • ✅ Centralized API key validation
  • ✅ Standard JWT-based authorization throughout system
See ADR-0034: API Key JWT Exchange for design details.

Comparison with Other Auth Methods

FeatureAPI KeysService PrincipalsJWT TokensSessions
LifespanDays-YearsPermanentMinutes-HoursHours-Days
Use CaseScripts, CLIServicesUser authWeb apps
IdentityUserMachineUserUser
RotationManualManualAutomaticN/A
Limit5 per userUnlimitedN/AConfigurable
RevocationImmediateImmediateWait for expiryImmediate


Secure & Scalable: API keys use bcrypt hashing and integrate seamlessly with Kong gateway!