> ## Documentation Index
> Fetch the complete documentation index at: https://docs.ensemble.ai/llms.txt
> Use this file to discover all available pages before exploring further.

# Authentication

> Secure your API access with tokens and scopes

## API Tokens

All API requests require a Bearer token:

```http theme={null}
Authorization: Bearer sk-ensemble-abc123...
```

## Get API Token

### Via CLI

```bash theme={null}
ensemble conductor auth:token
```

Output:

```
API Token: sk-ensemble-abc123def456...
Expires: Never
Scopes: read:ensembles, execute:ensembles, write:ensembles
```

### Via Dashboard

1. Navigate to Settings  API Tokens
2. Click "Create Token"
3. Select scopes
4. Copy token (shown only once)

## Token Scopes

Control access with fine-grained scopes:

### Read Scopes

* `read:ensembles` - List and view ensembles
* `read:agents` - List and view agents
* `read:executions` - View execution history
* `read:components` - View components
* `read:state` - Read ensemble state

### Write Scopes

* `write:ensembles` - Create/update ensembles
* `write:agents` - Create/update agents
* `write:components` - Create/update components
* `write:state` - Update ensemble state

### Execute Scopes

* `execute:ensembles` - Execute ensembles
* `execute:agents` - Execute agents

### Admin Scopes

* `admin` - Full access to all resources

## Scope Examples

### Read-Only Token

```json theme={null}
{
  "scopes": [
    "read:ensembles",
    "read:agents",
    "read:executions"
  ]
}
```

Use case: Monitoring, analytics

### Execution Token

```json theme={null}
{
  "scopes": [
    "execute:ensembles",
    "execute:agents",
    "read:executions"
  ]
}
```

Use case: Application integration

### Full Access Token

```json theme={null}
{
  "scopes": ["admin"]
}
```

Use case: Development, CI/CD

## Token Management

### Create Token

```bash theme={null}
curl -X POST https://your-worker.workers.dev/api/v1/tokens \
  -H "Authorization: Bearer ${ADMIN_TOKEN}" \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Production API Token",
    "scopes": ["execute:ensembles", "read:executions"],
    "expiresIn": 2592000
  }'
```

Response:

```json theme={null}
{
  "token": "sk-ensemble-abc123...",
  "id": "tok_abc123",
  "name": "Production API Token",
  "scopes": ["execute:ensembles", "read:executions"],
  "expiresAt": 1708000000000,
  "createdAt": 1705408000000
}
```

### List Tokens

```bash theme={null}
curl https://your-worker.workers.dev/api/v1/tokens \
  -H "Authorization: Bearer ${ADMIN_TOKEN}"
```

Response:

```json theme={null}
{
  "tokens": [
    {
      "id": "tok_abc123",
      "name": "Production API Token",
      "scopes": [...],
      "lastUsed": 1705408000000,
      "createdAt": 1705315200000
    }
  ]
}
```

### Revoke Token

```bash theme={null}
curl -X DELETE https://your-worker.workers.dev/api/v1/tokens/tok_abc123 \
  -H "Authorization: Bearer ${ADMIN_TOKEN}"
```

## Environment Variables

Store tokens securely:

### Local Development

```bash theme={null}
# .env.local
CONDUCTOR_API_TOKEN=sk-ensemble-abc123...
```

### Production (Wrangler)

```bash theme={null}
wrangler secret put CONDUCTOR_API_TOKEN
# Enter token when prompted
```

### Usage

```javascript theme={null}
const token = process.env.CONDUCTOR_API_TOKEN;

const response = await fetch('https://your-worker.workers.dev/api/v1/execute/ensemble/my-workflow', {
  method: 'POST',
  headers: {
    'Authorization': `Bearer ${token}`,
    'Content-Type': 'application/json'
  },
  body: JSON.stringify({ input: {...} })
});
```

## Security Best Practices

**1. Never Commit Tokens**

```bash theme={null}
# .gitignore
.env
.env.local
.env.*.local
```

**2. Use Minimal Scopes**

```json theme={null}
// Good: Only what's needed
{
  "scopes": ["execute:ensembles"]
}

// Bad: Over-permissioned
{
  "scopes": ["admin"]
}
```

**3. Rotate Tokens Regularly**

```bash theme={null}
# Create new token
ensemble conductor auth:token --name "Q1 2025"

# Update applications
# ...

# Revoke old token
ensemble conductor auth:revoke tok_old123
```

**4. Use Short-Lived Tokens**

```bash theme={null}
# 30-day expiration
ensemble conductor auth:token --expires-in 30d
```

**5. Monitor Token Usage**

```bash theme={null}
# Check last used
ensemble conductor tokens:list

# View activity
ensemble conductor tokens:activity tok_abc123
```

## Error Handling

### Missing Token

Request:

```http theme={null}
GET /ensembles
```

Response (401):

```json theme={null}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Missing authorization header"
  }
}
```

### Invalid Token

Request:

```http theme={null}
GET /ensembles
Authorization: Bearer invalid-token
```

Response (401):

```json theme={null}
{
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API token"
  }
}
```

### Insufficient Scope

Request:

```http theme={null}
POST /ensembles
Authorization: Bearer sk-ensemble-read-only...
```

Response (403):

```json theme={null}
{
  "error": {
    "code": "FORBIDDEN",
    "message": "Insufficient scope: requires write:ensembles",
    "requiredScope": "write:ensembles",
    "providedScopes": ["read:ensembles"]
  }
}
```

### Expired Token

Response (401):

```json theme={null}
{
  "error": {
    "code": "TOKEN_EXPIRED",
    "message": "API token expired",
    "expiredAt": 1705315200000
  }
}
```

## OAuth (Future)

OAuth 2.0 support coming soon:

```javascript theme={null}
// Future API
const oauth = new ConductorOAuth({
  clientId: 'your-client-id',
  redirectUri: 'https://yourapp.com/callback'
});

const authUrl = oauth.getAuthorizationUrl();
// Redirect user to authUrl

// In callback handler
const token = await oauth.exchangeCode(code);
```

## Next Steps

<CardGroup cols={2}>
  <Card title="Endpoints" icon="route" href="/api/http/endpoints">
    API endpoints
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/api/http/rate-limits">
    Rate limiting
  </Card>

  <Card title="Webhooks" icon="webhook" href="/api/http/webhooks">
    Webhook auth
  </Card>

  <Card title="Security Guide" icon="shield" href="/conductor/building/testing-observability">
    Security best practices
  </Card>
</CardGroup>
