API Keys

Learn how to manage authentication for CLI and API access in TeamDay.

Table of Contents

Authentication Methods

TeamDay supports two authentication methods:

MethodUse CaseExpirationBest For
OAuth 2.1CLI interactive use15 min (access token)
90 days (refresh token)
Human users, development
Personal Access Token (PAT)API automationManual revoke onlyCI/CD, scripts, automation

OAuth vs PAT

Use OAuth when:

  • Working interactively with CLI
  • You're a human user
  • You want automatic token refresh
  • Short-term access is preferred

Use PAT when:

  • Automating with scripts or CI/CD
  • Running background jobs
  • Need long-term access
  • Want simple bearer token auth

Personal Access Tokens

Personal Access Tokens (PATs) are long-lived credentials for programmatic access.

Creating a PAT

Via UI:

Step 1: Navigate to Settings

Click your profile icon → Settings

Step 2: Go to API Keys

Click "API Keys" in the left sidebar

Step 3: Click "Create Token"

Click the "+ New Personal Access Token" button

Step 4: Configure Token

  • Name (Required)
    • Descriptive name for this token
    • Examples: "CI/CD Pipeline", "Automation Scripts", "Production Bot"
  • Expiration (Optional)
    • Default: No expiration
    • Options: 30 days, 90 days, 1 year, custom, never
    • Recommendation: Set expiration for security
  • Scopes (Coming Soon)
    • Currently: Full access
    • Future: Fine-grained permissions (agents:read, tasks:write, etc.)

Step 5: Copy Token

⚠️ IMPORTANT: Token shown only once!

td_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6
  • Copy immediately and store securely
  • If lost, you must revoke and create new token
  • Never commit to git or share publicly

Step 6: Save Token Securely

Store in password manager or secure environment variable:

# .bashrc or .zshrc
export TEAMDAY_API_TOKEN="td_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

Using PATs

With CLI:

# Method 1: Set via command
teamday auth set-key "td_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

# Method 2: Environment variable
export TEAMDAY_API_TOKEN="td_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"
teamday agents list

# Method 3: Inline
TEAMDAY_API_TOKEN="td_xxx" teamday agents list

With API:

curl -X GET https://cc.teamday.ai/api/v1/agents \
  -H "Authorization: Bearer td_a1b2c3d4e5f6g7h8i9j0k1l2m3n4o5p6"

With JavaScript:

const TEAMDAY_TOKEN = process.env.TEAMDAY_API_TOKEN;

const response = await fetch('https://cc.teamday.ai/api/v1/agents', {
  headers: {
    'Authorization': `Bearer ${TEAMDAY_TOKEN}`,
    'Content-Type': 'application/json'
  }
});

const agents = await response.json();

With Python:

import os
import requests

TEAMDAY_TOKEN = os.environ['TEAMDAY_API_TOKEN']

response = requests.get(
    'https://cc.teamday.ai/api/v1/agents',
    headers={
        'Authorization': f'Bearer {TEAMDAY_TOKEN}',
        'Content-Type': 'application/json'
    }
)

agents = response.json()

Managing PATs

View Active Tokens:

Via UI:

  1. Settings → API Keys
  2. See list of active tokens with:
    • Name
    • Created date
    • Last used date
    • Expiration (if set)

Tokens are hashed - You can't view the token value after creation.

Via CLI:

teamday auth tokens list

Output:

ID          Name                    Created      Last Used    Expires
---------------------------------------------------------------------------
token_123   CI/CD Pipeline          2024-12-01   2025-01-15   2025-06-01
token_456   Production Bot          2024-10-15   2025-01-14   Never
token_789   Local Development       2025-01-10   2025-01-15   2025-02-10

Revoking PATs

Via UI:

  1. Settings → API Keys
  2. Find token in list
  3. Click "⋯" → "Revoke"
  4. Confirm

Via CLI:

teamday auth tokens revoke token_123

Effect:

  • Token immediately stops working
  • All requests with that token return 401 Unauthorized
  • Cannot be undone - must create new token

When to revoke:

  • Token potentially compromised
  • Employee leaves team
  • Switching to new token
  • Token no longer needed

Token Rotation

Best practice: Rotate tokens regularly

Strategy:

  1. Create new token
  2. Update systems to use new token
  3. Verify new token works
  4. Revoke old token

Example Script:

#!/bin/bash
# rotate-token.sh

# Create new token (via UI, copy value)
NEW_TOKEN="td_new_token_here"

# Update in CI/CD (example: GitHub Actions)
gh secret set TEAMDAY_API_TOKEN --body "$NEW_TOKEN"

# Update in production environment
kubectl create secret generic teamday-token \
  --from-literal=token="$NEW_TOKEN" \
  --dry-run=client -o yaml | kubectl apply -f -

# Test new token
TEAMDAY_API_TOKEN="$NEW_TOKEN" teamday agents list

# If successful, revoke old token
teamday auth tokens revoke token_old_id

OAuth for CLI

OAuth provides secure, short-lived access for CLI users.

How OAuth Works

sequenceDiagram
    participant CLI
    participant Browser
    participant TeamDay

    CLI->>TeamDay: 1. Initiate auth
    TeamDay->>CLI: 2. Return auth code + URL
    CLI->>Browser: 3. Open auth URL
    Browser->>TeamDay: 4. User logs in
    TeamDay->>Browser: 5. Authorization success
    CLI->>TeamDay: 6. Poll for tokens
    TeamDay->>CLI: 7. Return access + refresh tokens
    CLI->>TeamDay: 8. Make API requests
    Note over CLI,TeamDay: Access token expires in 15 min
    CLI->>TeamDay: 9. Refresh token
    TeamDay->>CLI: 10. New access token

Logging In with OAuth

Step 1: Run login command

teamday auth login

Step 2: CLI initiates auth

Initiating authentication...

Please open this URL in your browser:
https://cc.teamday.ai/cli-auth?code=abc123xyz

Waiting for authorization...

Step 3: Browser opens automatically

  • If browser doesn't open, copy/paste URL manually
  • You'll see TeamDay login page

Step 4: Log in to TeamDay

  • Enter email/password
  • Or use OAuth provider (Google, GitHub)

Step 5: Authorize CLI

Page shows:

Authorize TeamDay CLI

The TeamDay CLI is requesting access to your account.

This will allow:
✓ Manage agents
✓ Execute agents
✓ Access spaces
✓ Create tasks

[Authorize] [Cancel]

Click "Authorize"

Step 6: Success

Browser shows:

✓ Authorization successful!

You can close this window and return to your terminal.

CLI shows:

✓ Authentication successful!

You are now logged in as: [email protected]
Organization: Acme Corp

Token Storage

OAuth tokens stored locally:

Location:

  • macOS: ~/.teamday/config.json
  • Linux: ~/.teamday/config.json
  • Windows: %USERPROFILE%\.teamday\config.json

Contents:

{
  "accessToken": "ey...",
  "refreshToken": "ey...",
  "expiresAt": "2025-01-15T11:00:00Z",
  "user": {
    "email": "[email protected]",
    "organizationId": "org_abc123"
  }
}

Security:

  • File has strict permissions (600 on Unix)
  • Tokens encrypted at rest (on some systems)
  • Automatically refreshed before expiry

Automatic Token Refresh

CLI automatically refreshes access tokens:

# First command: Token valid
teamday agents list
# Works immediately

# ... 15 minutes later, token expired ...

# Next command: Token auto-refreshed
teamday agents exec char_123 "message"
# CLI detects expiration, refreshes token, then executes

Manual refresh:

teamday auth refresh

Checking Auth Status

teamday auth status

Output:

✓ Authenticated

User: [email protected]
Organization: Acme Corp
Method: OAuth
Access Token: Valid (expires in 12 min)
Refresh Token: Valid (expires in 85 days)

Logging Out

teamday auth logout

This:

  • Deletes local tokens
  • Revokes access token on server
  • Requires re-authentication for next command

Security Best Practices

1. Never Commit Tokens to Git

Use .gitignore:

# .gitignore
.env
.env.local
.teamday/
config.json
*_token.txt

Check before commit:

git diff --cached | grep -i "td_"

2. Use Environment Variables

For PATs:

# .env (DO NOT COMMIT)
TEAMDAY_API_TOKEN=td_xxx

# Load in scripts
export $(cat .env | xargs)

In CI/CD:

  • GitHub Actions: Repository Secrets
  • GitLab CI: CI/CD Variables
  • CircleCI: Project Settings → Environment Variables

3. Principle of Least Privilege

Create separate tokens for different purposes:

✓ Good:
- "CI/CD Deploy" - Only used in deployment pipeline
- "Daily Reports" - Only used for automated reporting
- "Development" - Used locally, rotated frequently

✗ Bad:
- "Master Token" - Used everywhere (if compromised, full access)

4. Set Expiration Dates

For automation tokens:

Short-lived projects: 30 days
Long-running CI/CD: 90 days
Review quarterly: 1 year

Review before expiration:

  • Set calendar reminders
  • Automate expiration notifications
  • Rotate proactively

5. Monitor Token Usage

Via UI: Settings → API Keys → View "Last Used"

Red flags:

  • Tokens never used (delete them)
  • Unexpected usage times (investigate)
  • High request volume (potential abuse)

6. Secure Token Storage

Local Development:

# Use a password manager
# Example: 1Password, LastPass, Bitwarden

# Or encrypted file
gpg --encrypt --recipient [email protected] token.txt
# Decrypt when needed
gpg --decrypt token.txt.gpg

Production:

# Use secret management
# AWS: Secrets Manager
# GCP: Secret Manager
# Azure: Key Vault
# Kubernetes: Secrets

7. Rotate Regularly

Recommended schedule:

  • Development tokens: Monthly
  • CI/CD tokens: Quarterly
  • Production tokens: Every 6 months
  • On team changes: Immediately

8. Audit Access

Monthly audit:

# List all tokens
teamday auth tokens list

# Check each:
# - Still needed?
# - Owner still on team?
# - Last used recently?
# - Expiration appropriate?

# Revoke unnecessary tokens
teamday auth tokens revoke token_old_id

9. Incident Response

If token compromised:

Step 1: Revoke immediately

teamday auth tokens revoke token_compromised_id

Step 2: Review audit logs

teamday audit --token token_compromised_id --since "1 week ago"

Step 3: Assess damage

  • What agents were accessed?
  • What data was exposed?
  • Were any destructive actions taken?

Step 4: Rotate all tokens

  • Don't know which was compromised? Rotate all

Step 5: Update documentation

  • How was it compromised?
  • How to prevent in future?

10. Rate Limiting

Be aware of rate limits:

  • With PAT: 1000 requests/hour
  • With OAuth: 500 requests/hour

Avoid:

# Bad: Polling in tight loop
while true; do
  teamday agents list
  sleep 1
done

Do:

# Good: Reasonable polling
while true; do
  teamday agents list
  sleep 60  # Check every minute
done

Troubleshooting

Invalid Token Error

Symptoms:

Error: Invalid token or token expired
Status: 401 Unauthorized

Solutions:

For PAT:

# Verify token is correct
echo $TEAMDAY_API_TOKEN

# Check if token is active
teamday auth tokens list

# Create new token if needed
# (via UI: Settings → API Keys → New Token)

For OAuth:

# Token expired, refresh
teamday auth refresh

# Or re-login
teamday auth logout
teamday auth login

Permission Denied

Symptoms:

Error: You do not have permission to perform this action
Status: 403 Forbidden

Causes:

  • Token has insufficient scopes (future feature)
  • User role doesn't allow action
  • Resource belongs to different organization

Solutions:

# Check auth status
teamday auth status

# Verify organization
teamday config get organization

# Switch organization (if member of multiple)
teamday config set organization org_different_id

Token Not Found

Symptoms:

Error: No authentication token found

Solutions:

# Check if logged in
teamday auth status

# If not, login
teamday auth login

# Or set PAT
teamday auth set-key "td_xxx"

# Or use environment variable
export TEAMDAY_API_TOKEN="td_xxx"

OAuth Flow Hangs

Symptoms: Browser never shows success page

Solutions:

1. Check browser console for errors

2. Manual completion:

# Cancel hanging flow
Ctrl+C

# Try again with manual code entry
teamday auth login --manual

3. Use PAT instead:

# Generate PAT via UI
# Then set in CLI
teamday auth set-key "td_xxx"

Rate Limit Exceeded

Symptoms:

Error: Rate limit exceeded
Status: 429 Too Many Requests
Retry-After: 3600

Solutions:

# Wait for rate limit reset (1 hour)

# Or implement exponential backoff
#!/bin/bash
retry=0
max_retries=5
while [ $retry -lt $max_retries ]; do
  if teamday agents list; then
    exit 0
  fi
  wait=$((2 ** retry))
  echo "Retrying in ${wait}s..."
  sleep $wait
  retry=$((retry + 1))
done

Next Steps