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

# Authentication

> Secure API authentication with JobHive using API keys and best practices

## API Key Authentication

JobHive uses API key authentication to secure all API endpoints. Your API key must be included in the `Authorization` header of every request.

### Getting Your API Key

<Steps>
  <Step title="Access Your Dashboard">
    Log into your JobHive dashboard at [app.jobhive.ai](https://app.jobhive.ai)
  </Step>

  <Step title="Navigate to API Settings">
    Go to **Settings** → **API Keys** in the main navigation
  </Step>

  <Step title="Generate New Key">
    Click **"Generate New API Key"** and provide a descriptive name for identification
  </Step>

  <Step title="Copy and Store Securely">
    Copy your API key immediately - it will only be shown once. Store it securely in your environment variables.
  </Step>
</Steps>

### Authentication Format

Include your API key in the `Authorization` header using the Bearer token format:

```bash theme={null}
Authorization: Bearer YOUR_API_KEY
```

### Example Requests

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://backend.jobhive.ai/v1/interviews" \
    -H "Authorization: Bearer jh_live_abc123def456ghi789" \
    -H "Content-Type: application/json"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://backend.jobhive.ai/v1/interviews', {
    method: 'GET',
    headers: {
      'Authorization': 'Bearer jh_live_abc123def456ghi789',
      'Content-Type': 'application/json'
    }
  });
  ```

  ```python Python theme={null}
  import requests

  headers = {
      'Authorization': 'Bearer jh_live_abc123def456ghi789',
      'Content-Type': 'application/json'
  }

  response = requests.get('https://backend.jobhive.ai/v1/interviews', headers=headers)
  ```
</CodeGroup>

## API Key Types & Environments

### Key Formats

JobHive API keys follow a consistent format for easy identification:

| Environment     | Format      | Example                |
| --------------- | ----------- | ---------------------- |
| **Development** | `jh_dev_*`  | `jh_dev_abc123def456`  |
| **Production**  | `jh_live_*` | `jh_live_xyz789ghi012` |
| **Test Mode**   | `jh_test_*` | `jh_test_mno345pqr678` |

### Environment Separation

<Tabs>
  <Tab title="Development Keys">
    **Purpose**: Local development and testing

    **Features**:

    * Access to sandbox environment
    * Unlimited test interviews
    * No billing or credit consumption
    * Separate data isolation

    **Limitations**:

    * Cannot create production interviews
    * Results not stored permanently
    * Limited to development features
  </Tab>

  <Tab title="Production Keys">
    **Purpose**: Live application integration

    **Features**:

    * Full platform access
    * Real interview creation and processing
    * Production-grade SLA and support
    * Complete feature access

    **Usage**:

    * Consumes account credits/quota
    * Results stored permanently
    * Used for actual candidate interviews
  </Tab>

  <Tab title="Test Mode Keys">
    **Purpose**: Integration testing without consuming credits

    **Features**:

    * Production environment access
    * No credit consumption
    * Realistic API responses
    * Safe for automated testing

    **Behavior**:

    * Interviews marked as test mode
    * No candidate notifications sent
    * Results available but flagged as test
  </Tab>
</Tabs>

## Security Best Practices

### API Key Management

<CardGroup cols={2}>
  <Card title="Secure Storage" icon="vault">
    **Do's**

    * Store in environment variables
    * Use secret management systems
    * Rotate keys regularly (quarterly)
    * Use different keys per environment
  </Card>

  <Card title="Usage Protection" icon="shield">
    **Don'ts**

    * Never commit keys to version control
    * Don't expose in client-side code
    * Avoid logging keys in application logs
    * Don't share keys via email or chat
  </Card>
</CardGroup>

### Environment Variable Setup

<CodeGroup>
  ```bash .env theme={null}
  # JobHive API Configuration
  JOBHIVE_API_KEY=jh_live_your_production_key_here
  JOBHIVE_WEBHOOK_SECRET=whsec_your_webhook_secret_here
  JOBHIVE_ENVIRONMENT=production

  # Development overrides
  # JOBHIVE_API_KEY=jh_dev_your_development_key_here  
  # JOBHIVE_ENVIRONMENT=development
  ```

  ```javascript JavaScript theme={null}
  // Using environment variables
  const apiKey = process.env.JOBHIVE_API_KEY;
  const environment = process.env.JOBHIVE_ENVIRONMENT || 'development';

  if (!apiKey) {
    throw new Error('JOBHIVE_API_KEY environment variable is required');
  }

  const client = new JobHive({
    apiKey: apiKey,
    environment: environment
  });
  ```

  ```python Python theme={null}
  import os
  from jobhive import JobHive

  api_key = os.environ.get('JOBHIVE_API_KEY')
  environment = os.environ.get('JOBHIVE_ENVIRONMENT', 'development')

  if not api_key:
      raise ValueError('JOBHIVE_API_KEY environment variable is required')

  client = JobHive(
      api_key=api_key,
      environment=environment
  )
  ```
</CodeGroup>

### Key Rotation

Regular API key rotation is a security best practice:

<Steps>
  <Step title="Generate New Key">
    Create a new API key in your dashboard before the current one expires
  </Step>

  <Step title="Update Applications">
    Deploy the new key to all applications and environments
  </Step>

  <Step title="Monitor Usage">
    Verify that all systems are using the new key successfully
  </Step>

  <Step title="Revoke Old Key">
    Delete the old API key from your dashboard once migration is complete
  </Step>
</Steps>

## Error Handling

### Authentication Errors

<ResponseExample>
  ```json 401 Unauthorized - Missing API Key theme={null}
  {
    "success": false,
    "error": {
      "code": "AUTHENTICATION_REQUIRED",
      "message": "API key is required. Include 'Authorization: Bearer YOUR_API_KEY' header.",
      "details": {
        "header_missing": "Authorization"
      }
    }
  }
  ```

  ```json 401 Unauthorized - Invalid API Key theme={null}
  {
    "success": false,
    "error": {
      "code": "INVALID_API_KEY",
      "message": "The provided API key is invalid or has been revoked.",
      "details": {
        "key_prefix": "jh_live_abc123"
      }
    }
  }
  ```

  ```json 401 Unauthorized - Expired API Key theme={null}
  {
    "success": false,
    "error": {
      "code": "API_KEY_EXPIRED",
      "message": "Your API key has expired. Please generate a new one.",
      "details": {
        "expired_at": "2024-01-15T10:30:00Z",
        "renewal_url": "https://app.jobhive.ai/settings/api-keys"
      }
    }
  }
  ```

  ```json 403 Forbidden - Insufficient Permissions theme={null}
  {
    "success": false,
    "error": {
      "code": "INSUFFICIENT_PERMISSIONS",
      "message": "Your API key does not have permission for this operation.",
      "details": {
        "required_permission": "interviews:write",
        "current_permissions": ["interviews:read"]
      }
    }
  }
  ```
</ResponseExample>

### Handling Authentication Errors

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function makeAuthenticatedRequest(url, options = {}) {
    const response = await fetch(url, {
      ...options,
      headers: {
        'Authorization': `Bearer ${process.env.JOBHIVE_API_KEY}`,
        'Content-Type': 'application/json',
        ...options.headers
      }
    });

    if (response.status === 401) {
      const error = await response.json();
      
      switch (error.error.code) {
        case 'AUTHENTICATION_REQUIRED':
          throw new Error('API key is missing from request');
        case 'INVALID_API_KEY':
          throw new Error('API key is invalid - check your environment variables');
        case 'API_KEY_EXPIRED':
          throw new Error('API key has expired - generate a new one');
        default:
          throw new Error(`Authentication failed: ${error.error.message}`);
      }
    }

    return response;
  }
  ```

  ```python Python theme={null}
  import requests
  from requests.exceptions import HTTPError

  def make_authenticated_request(url, **kwargs):
      headers = kwargs.get('headers', {})
      headers.update({
          'Authorization': f'Bearer {os.environ["JOBHIVE_API_KEY"]}',
          'Content-Type': 'application/json'
      })
      kwargs['headers'] = headers
      
      response = requests.request(**kwargs)
      
      if response.status_code == 401:
          error_data = response.json()
          error_code = error_data['error']['code']
          
          if error_code == 'AUTHENTICATION_REQUIRED':
              raise AuthenticationError('API key is missing from request')
          elif error_code == 'INVALID_API_KEY':
              raise AuthenticationError('API key is invalid - check your environment')
          elif error_code == 'API_KEY_EXPIRED':
              raise AuthenticationError('API key has expired - generate a new one')
          else:
              raise AuthenticationError(f'Authentication failed: {error_data["error"]["message"]}')
      
      response.raise_for_status()
      return response
  ```
</CodeGroup>

## API Key Permissions

### Permission Scopes

API keys can be configured with specific permission scopes to limit access:

| Permission          | Description                     | Example Usage        |
| ------------------- | ------------------------------- | -------------------- |
| `interviews:read`   | View interview data and results | Dashboard analytics  |
| `interviews:write`  | Create and update interviews    | Scheduling system    |
| `interviews:delete` | Cancel and delete interviews    | Admin operations     |
| `webhooks:read`     | View webhook configurations     | Integration status   |
| `webhooks:write`    | Create and manage webhooks      | Event handling setup |
| `analytics:read`    | Access aggregate analytics      | Reporting systems    |

### Creating Scoped Keys

<Steps>
  <Step title="Navigate to API Keys">
    Go to Settings → API Keys in your dashboard
  </Step>

  <Step title="Click Advanced Options">
    Select "Create Key with Custom Permissions" instead of default key
  </Step>

  <Step title="Select Permissions">
    Choose only the permissions your application needs
  </Step>

  <Step title="Set Expiration">
    Optionally set an expiration date for additional security
  </Step>
</Steps>

## Rate Limiting & Quotas

### Rate Limit Headers

All API responses include rate limiting information:

```http theme={null}
X-RateLimit-Limit: 300
X-RateLimit-Remaining: 299  
X-RateLimit-Reset: 1640995200
X-RateLimit-Retry-After: 60
```

### Handling Rate Limits

<CodeGroup>
  ```javascript JavaScript theme={null}
  async function makeRateLimitedRequest(url, options) {
    const response = await fetch(url, options);
    
    if (response.status === 429) {
      const retryAfter = response.headers.get('X-RateLimit-Retry-After');
      console.log(`Rate limited. Retrying after ${retryAfter} seconds`);
      
      await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
      return makeRateLimitedRequest(url, options); // Retry
    }
    
    return response;
  }
  ```

  ```python Python theme={null}
  import time
  import requests

  def make_rate_limited_request(url, **kwargs):
      response = requests.request(**kwargs)
      
      if response.status_code == 429:
          retry_after = int(response.headers.get('X-RateLimit-Retry-After', 60))
          print(f"Rate limited. Retrying after {retry_after} seconds")
          
          time.sleep(retry_after)
          return make_rate_limited_request(url, **kwargs)  # Retry
      
      return response
  ```
</CodeGroup>

## Testing Authentication

### Verify API Key

Test your API key with a simple request:

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET "https://backend.jobhive.ai/v1/account/profile" \
    -H "Authorization: Bearer YOUR_API_KEY"
  ```

  ```javascript JavaScript theme={null}
  async function testApiKey() {
    try {
      const response = await fetch('https://backend.jobhive.ai/v1/account/profile', {
        headers: {
          'Authorization': `Bearer ${process.env.JOBHIVE_API_KEY}`
        }
      });
      
      if (response.ok) {
        const profile = await response.json();
        console.log('API key is valid:', profile.data.company_name);
      } else {
        console.error('API key test failed:', response.status);
      }
    } catch (error) {
      console.error('API key test error:', error.message);
    }
  }
  ```

  ```python Python theme={null}
  def test_api_key():
      try:
          response = requests.get(
              'https://backend.jobhive.ai/v1/account/profile',
              headers={'Authorization': f'Bearer {os.environ["JOBHIVE_API_KEY"]}'}
          )
          
          if response.status_code == 200:
              profile = response.json()
              print(f'API key is valid: {profile["data"]["company_name"]}')
          else:
              print(f'API key test failed: {response.status_code}')
      except Exception as error:
          print(f'API key test error: {error}')
  ```
</CodeGroup>

Expected successful response:

```json theme={null}
{
  "success": true,
  "data": {
    "company_name": "Your Company",
    "plan": "Professional",
    "api_key_permissions": ["interviews:read", "interviews:write"],
    "rate_limit": {
      "requests_per_minute": 300,
      "current_usage": 1
    }
  }
}
```

<Note>
  **Security Tip**: Always test API keys in development before deploying to production. Use the account profile endpoint to verify both authentication and permissions.
</Note>

<Warning>
  **Important**: API keys provide full access to your JobHive account. Treat them like passwords and follow security best practices to protect your data and prevent unauthorized usage.
</Warning>
