Skip to main content

Authentication

Ozwell uses API keys to authenticate requests. This guide covers key types, security best practices, and implementation patterns.

API Key Types

Ozwell provides two types of API keys for different use cases:

Key TypePrefixUse CaseSecurity Level
General-Purposeozw_Server-side, full API accessServer-only
Scopedozw_scoped_Client-side, limited accessClient-safe

General-Purpose Keys

Full-access keys for server-side integrations:

  • ✅ Access all API endpoints
  • ✅ All models and capabilities
  • ✅ No agent restrictions
  • ⚠️ Never expose client-side
# Server-side usage only
export OZWELL_API_KEY="ozw_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx"

Scoped Keys

Restricted keys for client-side (frontend) integrations:

  • ✅ Tied to specific agent(s)
  • ✅ Permission-limited
  • ✅ Safe for browser use
  • ✅ Domain restrictions available
// Safe for frontend use
const apiKey = 'ozw_scoped_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx';

Creating API Keys

Via Dashboard

  1. Log in to Ozwell Dashboard
  2. Navigate to Settings → API Keys
  3. Click Create API Key or Create Scoped Key
  4. Configure permissions (for scoped keys)
  5. Copy the key immediately — it won't be shown again

Via API (Coming Soon)

curl https://api.ozwell.ai/v1/api-keys \
-H "Authorization: Bearer $OZWELL_API_KEY" \
-H "Content-Type: application/json" \
-d '{
"name": "Production Server",
"type": "general",
"permissions": ["*"]
}'

Using API Keys

Authorization Header

Include the API key in the Authorization header:

curl https://api.ozwell.ai/v1/chat/completions \
-H "Authorization: Bearer ozw_xxxxxxxx" \
-H "Content-Type: application/json" \
-d '{"model": "gpt-4", "messages": [{"role": "user", "content": "Hello"}]}'

SDK Configuration

import { OzwellClient } from '@ozwell/api';

const client = new OzwellClient({
apiKey: process.env.OZWELL_API_KEY,
});

OpenAI SDK Compatibility

import OpenAI from 'openai';

const client = new OpenAI({
apiKey: process.env.OZWELL_API_KEY,
baseURL: 'https://api.ozwell.ai/v1',
});

Security Best Practices

Never Expose Keys in Code

// ❌ BAD - Key in source code
const client = new OzwellClient({
apiKey: 'ozw_abc123...',
});

// ✅ GOOD - Key from environment
const client = new OzwellClient({
apiKey: process.env.OZWELL_API_KEY,
});

Use Environment Variables

# .env (never commit this file)
OZWELL_API_KEY=ozw_xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx

# .env.example (commit this as a template)
OZWELL_API_KEY=your_api_key_here
// Load from environment
import 'dotenv/config';

const client = new OzwellClient({
apiKey: process.env.OZWELL_API_KEY,
});

Separate Keys by Environment

Use different keys for each environment:

# Development
OZWELL_API_KEY=ozw_dev_xxxxxxxx

# Staging
OZWELL_API_KEY=ozw_staging_xxxxxxxx

# Production
OZWELL_API_KEY=ozw_prod_xxxxxxxx

Regular Key Rotation

Rotate API keys periodically:

  1. Create a new key in the dashboard
  2. Update your application configuration
  3. Deploy the change
  4. Verify the new key works
  5. Revoke the old key

Scoped Key Domain Restrictions

For frontend integrations, restrict scoped keys to specific domains:

  1. Go to Settings → API Keys
  2. Edit your scoped key
  3. Add allowed domains (e.g., example.com, *.example.com)
  4. Requests from other domains will be rejected

Error Handling

Invalid API Key

{
"error": {
"message": "Invalid API key provided",
"type": "authentication_error",
"code": "invalid_api_key"
}
}

HTTP Status: 401 Unauthorized

Missing API Key

{
"error": {
"message": "API key is required",
"type": "authentication_error",
"code": "missing_api_key"
}
}

HTTP Status: 401 Unauthorized

Insufficient Permissions

{
"error": {
"message": "API key does not have access to this resource",
"type": "permission_error",
"code": "insufficient_permissions"
}
}

HTTP Status: 403 Forbidden

Handling in Code

import { OzwellClient, OzwellError } from '@ozwell/api';

const client = new OzwellClient({
apiKey: process.env.OZWELL_API_KEY,
});

try {
const response = await client.chat.completions.create({
model: 'gpt-4',
messages: [{ role: 'user', content: 'Hello' }],
});
} catch (error) {
if (error instanceof OzwellError) {
switch (error.code) {
case 'invalid_api_key':
console.error('Check your API key configuration');
break;
case 'insufficient_permissions':
console.error('This key lacks required permissions');
break;
default:
console.error('API error:', error.message);
}
}
throw error;
}

Rate Limiting

API keys are rate-limited. When exceeded:

HTTP Status: 429 Too Many Requests

Headers:

X-RateLimit-Limit: 100
X-RateLimit-Remaining: 0
X-RateLimit-Reset: 1699000060
Retry-After: 30

Response:

{
"error": {
"message": "Rate limit exceeded. Please retry after 30 seconds.",
"type": "rate_limit_error",
"code": "rate_limit_exceeded"
}
}

Handling Rate Limits

async function makeRequestWithRetry(fn, maxRetries = 3) {
for (let i = 0; i < maxRetries; i++) {
try {
return await fn();
} catch (error) {
if (error instanceof OzwellError && error.code === 'rate_limit_exceeded') {
const retryAfter = error.headers?.['retry-after'] || 30;
console.log(`Rate limited. Retrying in ${retryAfter}s...`);
await new Promise(r => setTimeout(r, retryAfter * 1000));
} else {
throw error;
}
}
}
throw new Error('Max retries exceeded');
}

Key Management API

List Keys (Coming Soon)

GET /v1/api-keys

Revoke Key (Coming Soon)

DELETE /v1/api-keys/{key_id}

See Also