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

# Authentication Guide

> Complete guide to authenticating with the DRIP API

This guide covers everything you need to know about authenticating with the DRIP API, managing API keys, and handling authentication in your applications.

## Overview

The DRIP API uses **Bearer token authentication** with API keys. Every request must include a valid API key in the `Authorization` header.

## Managing API Keys

### Creating API Keys

<Steps>
  <Step title="Access Developer Portal">
    Navigate to your DRIP dashboard and go to **Admin** > **Developer**
  </Step>

  <Step title="Create API Client">
    Go to the **Project API** tab and click **Create API Client**. Choose appropriate scopes and provide a descriptive name
  </Step>

  <Step title="Copy and Store">
    Copy the API key immediately - you won't be able to see it again
  </Step>

  <Step title="Test the Key">
    Make a test API call to verify the key works correctly
  </Step>
</Steps>

## Implementation Examples

### Environment Variables

Store your API keys securely using environment variables:

<Info>
  **Finding your Realm (Project) ID:** It's displayed in the dashboard header when you select your project.
</Info>

<CodeGroup>
  ```bash .env theme={"dark"}
  DRIP_API_KEY=your_api_key_here
  DRIP_REALM_ID=your_realm_id_here
  DRIP_BASE_URL=https://api.drip.re/api/v1
  ```

  ```javascript JavaScript theme={"dark"}
  // Load from environment
  const DRIP_API_KEY = process.env.DRIP_API_KEY;
  const DRIP_REALM_ID = process.env.DRIP_REALM_ID;

  // Create headers
  const headers = {
    'Authorization': `Bearer ${DRIP_API_KEY}`,
    'Content-Type': 'application/json'
  };
  ```

  ```python Python theme={"dark"}
  import os

  # Load from environment
  DRIP_API_KEY = os.getenv('DRIP_API_KEY')
  DRIP_REALM_ID = os.getenv('DRIP_REALM_ID')

  # Create headers
  headers = {
      'Authorization': f'Bearer {DRIP_API_KEY}',
      'Content-Type': 'application/json'
  }
  ```
</CodeGroup>

### API Client Class

Create a reusable client class for your applications:

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  class DripClient {
    constructor(apiKey, realmId) {
      this.apiKey = apiKey;
      this.realmId = realmId;
      this.baseUrl = 'https://api.drip.re/api/v1';
    }

    async request(method, endpoint, data = null) {
      const url = `${this.baseUrl}${endpoint}`;
      const options = {
        method,
        headers: {
          'Authorization': `Bearer ${this.apiKey}`,
          'Content-Type': 'application/json'
        }
      };

      if (data) {
        options.body = JSON.stringify(data);
      }

      const response = await fetch(url, options);
      
      if (!response.ok) {
        throw new Error(`API Error: ${response.status} ${response.statusText}`);
      }

      return response.json();
    }

    // Helper methods
    async getRealm() {
      return this.request('GET', `/realms/${this.realmId}`);
    }

    async searchMembers(type, values) {
      return this.request('GET', `/realm/${this.realmId}/members/search?type=${type}&values=${values}`);
    }
  }

  // Usage
  const client = new DripClient(process.env.DRIP_API_KEY, process.env.DRIP_REALM_ID);
  ```

  ```python Python theme={"dark"}
  import requests
  import json

  class DripClient:
      def __init__(self, api_key, realm_id):
          self.api_key = api_key
          self.realm_id = realm_id
          self.base_url = 'https://api.drip.re/api/v1'
          self.headers = {
              'Authorization': f'Bearer {api_key}',
              'Content-Type': 'application/json'
          }

      def request(self, method, endpoint, data=None):
          url = f"{self.base_url}{endpoint}"
          
          response = requests.request(
              method=method,
              url=url,
              headers=self.headers,
              json=data if data else None
          )
          
          response.raise_for_status()
          return response.json()

      def get_realm(self):
          return self.request('GET', f'/realms/{self.realm_id}')

      def search_members(self, search_type, values):
          return self.request('GET', f'/realm/{self.realm_id}/members/search?type={search_type}&values={values}')

  # Usage
  client = DripClient(os.getenv('DRIP_API_KEY'), os.getenv('DRIP_REALM_ID'))
  ```
</CodeGroup>

## Error Handling

Handle authentication errors gracefully:

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  async function handleApiCall(apiCall) {
    try {
      return await apiCall();
    } catch (error) {
      if (error.status === 401) {
        console.error('Authentication failed - check your API key');
        // Redirect to re-authenticate or refresh key
      } else if (error.status === 403) {
        console.error('Insufficient permissions for this operation');
      } else {
        console.error('API call failed:', error.message);
      }
      throw error;
    }
  }
  ```

  ```python Python theme={"dark"}
  def handle_api_call(api_call):
      try:
          return api_call()
      except requests.exceptions.HTTPError as e:
          if e.response.status_code == 401:
              print("Authentication failed - check your API key")
              # Handle re-authentication
          elif e.response.status_code == 403:
              print("Insufficient permissions for this operation")
          else:
              print(f"API call failed: {e}")
          raise
  ```
</CodeGroup>

## Security Best Practices

<CardGroup cols={2}>
  <Card title="Secure Storage" icon="vault">
    * Store API keys in environment variables
    * Use secure key management services in production
    * Never commit keys to version control
  </Card>

  <Card title="Key Rotation" icon="arrows-rotate">
    * Rotate API keys regularly (monthly/quarterly)
    * Have a process for emergency key rotation
    * Revoke unused or compromised keys immediately
  </Card>

  <Card title="Network Security" icon="shield">
    * Always use HTTPS for API requests
    * Implement request signing for extra security
    * Use IP allowlisting when possible
  </Card>

  <Card title="Monitoring" icon="chart-line">
    * Monitor API key usage patterns
    * Set up alerts for unusual activity
    * Log authentication failures for security analysis
  </Card>
</CardGroup>

## Testing Authentication

Use this simple test to verify your authentication setup:

<CodeGroup>
  ```javascript JavaScript theme={"dark"}
  async function testAuth() {
    try {
      const response = await fetch(`https://api.drip.re/api/v1/realms/${DRIP_REALM_ID}`, {
        headers: {
          'Authorization': `Bearer ${DRIP_API_KEY}`
        }
      });

      if (response.ok) {
        const realm = await response.json();
        console.log('✅ Authentication successful!');
        console.log(`Connected to realm: ${realm.name}`);
      } else {
        console.log('❌ Authentication failed');
      }
    } catch (error) {
      console.error('Error testing authentication:', error);
    }
  }
  ```

  ```python Python theme={"dark"}
  def test_auth():
      try:
          response = requests.get(
              f'https://api.drip.re/api/v1/realms/{DRIP_REALM_ID}',
              headers={'Authorization': f'Bearer {DRIP_API_KEY}'}
          )
          
          if response.ok:
              realm = response.json()
              print("✅ Authentication successful!")
              print(f"Connected to realm: {realm['name']}")
          else:
              print("❌ Authentication failed")
              
      except Exception as e:
          print(f"Error testing authentication: {e}")
  ```

  ```bash cURL theme={"dark"}
  # Test authentication
  curl -X GET "https://api.drip.re/api/v1/realms/YOUR_REALM_ID" \
    -H "Authorization: Bearer YOUR_API_KEY" \
    -w "\nStatus: %{http_code}\n"
  ```
</CodeGroup>

## Troubleshooting

Common authentication issues and solutions:

<AccordionGroup>
  <Accordion title="401 Unauthorized">
    **Causes:**

    * Invalid or expired API key
    * Missing Authorization header
    * Incorrect Bearer token format

    **Solutions:**

    * Verify API key is correct and active
    * Check header format: `Authorization: Bearer YOUR_KEY`
    * Generate a new API key if needed
  </Accordion>

  <Accordion title="403 Forbidden">
    **Causes:**

    * API key lacks required permissions
    * Trying to access resources outside your realm
    * Account permissions changed

    **Solutions:**

    * Check your account permissions in the dashboard
    * Ensure you're accessing the correct realm
    * Contact an admin to update permissions
  </Accordion>

  <Accordion title="Rate Limiting">
    **Causes:**

    * Too many requests in a short time
    * Exceeding API quotas

    **Solutions:**

    * Implement exponential backoff
    * Check rate limit headers in responses
    * Optimize request frequency
  </Accordion>
</AccordionGroup>
