Skip to main content

Overview

The better-openclaw API supports optional API key authentication via the X-API-Key header. Authentication is disabled by default - when no API keys are configured, all requests are accepted.

Configuration

Configure valid API keys using the API_KEYS environment variable:
export API_KEYS="sk_live_abc123,sk_live_def456,sk_test_xyz789"
Multiple keys can be comma-separated. When API_KEYS is set:
  • Requests with a valid key are accepted
  • Requests with an invalid key receive a 401 Unauthorized response
  • Requests without a key are still accepted (but subject to lower rate limits)

Making Authenticated Requests

Include your API key in the X-API-Key header:
curl http://localhost:3456/v1/services \
  -H "X-API-Key: sk_live_abc123"

Example: Generate Stack with Authentication

curl -X POST http://localhost:3456/v1/generate \
  -H "Content-Type: application/json" \
  -H "X-API-Key: sk_live_abc123" \
  -d '{
    "projectName": "my-stack",
    "services": ["postgresql", "redis"],
    "proxy": "caddy"
  }'

Authentication Errors

Invalid API Key

Request:
curl http://localhost:3456/v1/services \
  -H "X-API-Key: invalid_key"
Response (401):
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key."
  }
}

Security Best Practices

Key Format Recommendations

Use descriptive prefixes to identify key types:
  • sk_live_ - Production keys
  • sk_test_ - Development/testing keys
  • sk_dev_ - Local development keys

Key Generation

Generate secure random keys using:
# Generate a secure API key
openssl rand -hex 32

# Or use Node.js
node -e "console.log('sk_live_' + require('crypto').randomBytes(32).toString('hex'))"

Environment Variables

Never commit API keys to version control. Use environment files:
# .env (add to .gitignore)
API_KEYS=sk_live_abc123,sk_live_def456
Load with Docker Compose:
services:
  api:
    image: better-openclaw-api
    env_file:
      - .env

Rate Limiting Benefits

Authenticated requests receive higher rate limits:
Request TypeUnauthenticatedAuthenticated
Standard endpoints100/15min500/15min
Generate endpoint10/15min50/15min

Security Features

Timing-Safe Comparison

API keys are validated using SHA-256 hashes with constant-time comparison to prevent timing attacks:
// Pseudocode - actual implementation in middleware
const keyHash = sha256(providedKey);
const isValid = timingSafeEqual(keyHash, storedHash);

No Key Storage

Keys are hashed in memory - raw keys are never stored on disk.

Development vs Production

Development (No Authentication)

For local development, run without API_KEYS:
npm run dev
# All requests accepted, no X-API-Key required

Production (With Authentication)

For production, always configure API_KEYS:
export API_KEYS="sk_live_production_key_here"
npm start

Testing Authentication

Health Check (No Auth Required)

curl http://localhost:3456/v1/health
# Always works, regardless of API_KEYS configuration

Protected Endpoint Test

# Without API key (works if API_KEYS not set)
curl http://localhost:3456/v1/services

# With valid API key
curl http://localhost:3456/v1/services \
  -H "X-API-Key: sk_live_abc123"

# With invalid API key (fails if API_KEYS is set)
curl http://localhost:3456/v1/services \
  -H "X-API-Key: invalid_key"

Troubleshooting

Check that your API_KEYS environment variable is set correctly and matches the key in your X-API-Key header. Verify no extra whitespace in the environment variable.
Ensure the API server was restarted after setting API_KEYS. Environment variables are loaded at startup.
Verify API_KEYS is passed to the container via env_file or environment in docker-compose.yml.

Next Steps

Services Endpoint

Browse available services with authentication

Generate Endpoint

Generate stacks with authenticated requests

Build docs developers (and LLMs) love