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

# Error Handling

> Understanding API errors and how to handle them properly

The Buena.ai API uses conventional HTTP status codes and returns detailed error information to help you debug issues quickly.

## Error Response Format

All errors follow a consistent JSON format:

```json theme={null}
{
  "error": true,
  "code": "ERROR_CODE",
  "message": "Human-readable error description",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "field": "Additional context when applicable"
  }
}
```

### Fields

| Field       | Description                       |
| ----------- | --------------------------------- |
| `error`     | Always `true` for error responses |
| `code`      | Machine-readable error code       |
| `message`   | Human-readable error description  |
| `version`   | API version                       |
| `timestamp` | ISO 8601 timestamp of the error   |
| `details`   | Additional context (optional)     |

## HTTP Status Codes

<CardGroup cols={2}>
  <Card title="2xx Success" icon="check">
    * `200` OK - Request succeeded - `201` Created - Resource created - `204` No
      Content - Request succeeded, no content
  </Card>

  <Card title="4xx Client Errors" icon="triangle-exclamation">
    * `400` Bad Request - Invalid request - `401` Unauthorized - Invalid API key
    * `403` Forbidden - Insufficient permissions - `404` Not Found - Resource
      not found - `429` Too Many Requests - Rate limited
  </Card>

  <Card title="5xx Server Errors" icon="server">
    * `500` Internal Server Error - Server issue - `502` Bad Gateway - Upstream
      error - `503` Service Unavailable - Temporary unavailability
  </Card>
</CardGroup>

## Common Error Codes

### Authentication Errors

#### UNAUTHORIZED (401)

```json theme={null}
{
  "error": true,
  "code": "UNAUTHORIZED",
  "message": "Invalid API key",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z"
}
```

**Causes:**

* Missing `x-api-key` header
* Invalid API key format
* Expired API key
* Deactivated API key

#### PERMISSION\_DENIED (403)

```json theme={null}
{
  "error": true,
  "code": "PERMISSION_DENIED",
  "message": "Insufficient permissions",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "permissionHelp": {
    "required": "linkedin:schedule",
    "available": ["linkedin:read"],
    "documentation": "https://docs.buena.ai/authentication"
  }
}
```

**Causes:**

* API key lacks required permission
* Attempting to access restricted resource

### Validation Errors

#### VALIDATION\_ERROR (400)

```json theme={null}
{
  "error": true,
  "code": "VALIDATION_ERROR",
  "message": "Invalid request data",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "fields": {
      "email": "Invalid email format",
      "firstName": "Field is required"
    }
  }
}
```

**Causes:**

* Missing required fields
* Invalid field formats
* Invalid field values

#### INVALID\_LINKEDIN\_URL (400)

```json theme={null}
{
  "error": true,
  "code": "INVALID_LINKEDIN_URL",
  "message": "Invalid LinkedIn profile URL format",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "providedUrl": "https://example.com/profile",
    "expectedFormat": "https://linkedin.com/in/username"
  }
}
```

### Rate Limiting Errors

#### RATE\_LIMIT\_EXCEEDED (429)

```json theme={null}
{
  "error": true,
  "code": "RATE_LIMIT_EXCEEDED",
  "message": "Rate limit exceeded. Try again in 45 seconds.",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "retryAfter": 45,
  "rateLimitInfo": {
    "limit": 60,
    "remaining": 0,
    "reset": 1640995245,
    "window": "minute"
  }
}
```

### Resource Errors

#### NOT\_FOUND (404)

```json theme={null}
{
  "error": true,
  "code": "NOT_FOUND",
  "message": "Lead not found",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "resource": "lead",
    "id": "lead_abc123"
  }
}
```

#### DUPLICATE\_RESOURCE (409)

```json theme={null}
{
  "error": true,
  "code": "DUPLICATE_RESOURCE",
  "message": "Lead with this email already exists",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "field": "email",
    "value": "john@example.com",
    "existingId": "lead_xyz789"
  }
}
```

### Integration Errors

#### LINKEDIN\_NOT\_CONNECTED (400)

```json theme={null}
{
  "error": true,
  "code": "LINKEDIN_NOT_CONNECTED",
  "message": "LinkedIn account not connected",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "action": "Connect your LinkedIn account in the dashboard",
    "dashboardUrl": "https://app.buena.ai/integrations/linkedin"
  }
}
```

#### ENRICHMENT\_CREDITS\_EXHAUSTED (402)

```json theme={null}
{
  "error": true,
  "code": "ENRICHMENT_CREDITS_EXHAUSTED",
  "message": "Insufficient enrichment credits",
  "version": "2.0",
  "timestamp": "2024-01-20T15:30:00Z",
  "details": {
    "remaining": 0,
    "required": 5,
    "upgradeUrl": "https://app.buena.ai/billing"
  }
}
```

## Error Handling Best Practices

<AccordionGroup>
  <Accordion title="Check Status Codes First">
    Always check the HTTP status code before parsing the response:

    ```javascript theme={null}
    async function makeRequest(url, options) {
      const response = await fetch(url, options);
      
      if (!response.ok) {
        const error = await response.json();
        throw new APIError(response.status, error);
      }
      
      return response.json();
    }

    class APIError extends Error {
      constructor(status, errorData) {
        super(errorData.message);
        this.status = status;
        this.code = errorData.code;
        this.details = errorData.details;
      }
    }
    ```
  </Accordion>

  <Accordion title="Handle Specific Error Codes">
    Different errors require different handling strategies:

    ```javascript theme={null}
    async function handleAPICall() {
      try {
        return await makeRequest('/leads', options);
      } catch (error) {
        switch (error.code) {
          case 'UNAUTHORIZED':
            // Refresh or request new API key
            await refreshAPIKey();
            break;
            
          case 'PERMISSION_DENIED':
            // Log permission issue, contact admin
            console.error('Missing permission:', error.details?.permissionHelp);
            break;
            
          case 'RATE_LIMIT_EXCEEDED':
            // Wait and retry
            await new Promise(resolve => 
              setTimeout(resolve, error.retryAfter * 1000)
            );
            return handleAPICall(); // Retry
            
          case 'VALIDATION_ERROR':
            // Fix validation issues
            console.error('Validation errors:', error.details?.fields);
            break;
            
          default:
            // Log unexpected error
            console.error('Unexpected error:', error);
        }
        
        throw error;
      }
    }
    ```
  </Accordion>

  <Accordion title="Implement Retry Logic">
    Retry transient errors with exponential backoff:

    ```javascript theme={null}
    async function retryableRequest(apiCall, maxRetries = 3) {
      const retryableCodes = [
        'RATE_LIMIT_EXCEEDED',
        'INTERNAL_SERVER_ERROR',
        'SERVICE_UNAVAILABLE'
      ];
      
      for (let attempt = 0; attempt < maxRetries; attempt++) {
        try {
          return await apiCall();
        } catch (error) {
          const isLastAttempt = attempt === maxRetries - 1;
          const isRetryable = retryableCodes.includes(error.code);
          
          if (isLastAttempt || !isRetryable) {
            throw error;
          }
          
          const delay = error.retryAfter ? 
            error.retryAfter * 1000 : 
            Math.pow(2, attempt) * 1000;
          
          await new Promise(resolve => setTimeout(resolve, delay));
        }
      }
    }
    ```
  </Accordion>

  <Accordion title="Log Errors Appropriately">
    Log errors with appropriate detail levels:

    ```javascript theme={null}
    function logError(error, context = {}) {
      const logData = {
        timestamp: new Date().toISOString(),
        status: error.status,
        code: error.code,
        message: error.message,
        context,
        ...error.details
      };
      
      // Different log levels based on error type
      if (error.status >= 500) {
        console.error('Server error:', logData);
      } else if (error.status === 429) {
        console.warn('Rate limited:', logData);
      } else if (error.status >= 400) {
        console.info('Client error:', logData);
      }
      
      // Send to monitoring service
      sendToMonitoring(logData);
    }
    ```
  </Accordion>
</AccordionGroup>

## Language-Specific Examples

### JavaScript/TypeScript

```typescript theme={null}
interface APIError {
  error: boolean;
  code: string;
  message: string;
  version: string;
  timestamp: string;
  details?: any;
}

class BuenaAPIClient {
  private apiKey: string;

  constructor(apiKey: string) {
    this.apiKey = apiKey;
  }

  async request<T>(endpoint: string, options: RequestInit = {}): Promise<T> {
    const response = await fetch(`https://api.buena.ai/api/v2${endpoint}`, {
      ...options,
      headers: {
        "x-api-key": this.apiKey,
        "Content-Type": "application/json",
        ...options.headers,
      },
    });

    const data = await response.json();

    if (!response.ok) {
      throw new BuenaAPIError(response.status, data);
    }

    return data;
  }
}

class BuenaAPIError extends Error {
  constructor(public status: number, public errorData: APIError) {
    super(errorData.message);
    this.name = "BuenaAPIError";
  }

  get code() {
    return this.errorData.code;
  }

  get details() {
    return this.errorData.details;
  }
}
```

### Python

```python theme={null}
import requests
from typing import Dict, Any, Optional
import time

class BuenaAPIError(Exception):
    def __init__(self, status_code: int, error_data: Dict[str, Any]):
        self.status_code = status_code
        self.error_data = error_data
        super().__init__(error_data.get('message', 'Unknown error'))

    @property
    def code(self) -> str:
        return self.error_data.get('code', 'UNKNOWN')

    @property
    def details(self) -> Optional[Dict[str, Any]]:
        return self.error_data.get('details')

class BuenaAPIClient:
    def __init__(self, api_key: str):
        self.api_key = api_key
        self.base_url = 'https://api.buena.ai/api/v2'

    def request(
        self,
        endpoint: str,
        method: str = 'GET',
        json_data: Optional[Dict] = None,
        max_retries: int = 3
    ) -> Dict[str, Any]:

        headers = {
            'x-api-key': self.api_key,
            'Content-Type': 'application/json'
        }

        for attempt in range(max_retries):
            try:
                response = requests.request(
                    method=method,
                    url=f'{self.base_url}{endpoint}',
                    headers=headers,
                    json=json_data
                )

                if response.ok:
                    return response.json()

                error_data = response.json()
                error = BuenaAPIError(response.status_code, error_data)

                # Handle specific error types
                if error.code == 'RATE_LIMIT_EXCEEDED':
                    if attempt < max_retries - 1:
                        retry_after = error_data.get('retryAfter', 2 ** attempt)
                        time.sleep(retry_after)
                        continue

                raise error

            except requests.RequestException as e:
                if attempt == max_retries - 1:
                    raise e
                time.sleep(2 ** attempt)
```

## Error Monitoring

### Setting Up Alerts

```javascript theme={null}
class ErrorMonitor {
  constructor(alertThreshold = 0.05) {
    this.alertThreshold = alertThreshold; // 5% error rate
    this.errorCounts = new Map();
    this.totalRequests = 0;
  }

  trackRequest(isError, errorCode = null) {
    this.totalRequests++;

    if (isError) {
      const count = this.errorCounts.get(errorCode) || 0;
      this.errorCounts.set(errorCode, count + 1);

      this.checkAlertThreshold();
    }
  }

  checkAlertThreshold() {
    const totalErrors = Array.from(this.errorCounts.values()).reduce(
      (sum, count) => sum + count,
      0
    );

    const errorRate = totalErrors / this.totalRequests;

    if (errorRate >= this.alertThreshold) {
      this.sendAlert(errorRate, this.errorCounts);
    }
  }

  sendAlert(errorRate, errorCounts) {
    console.error(`High error rate detected: ${(errorRate * 100).toFixed(2)}%`);
    console.error("Error breakdown:", Object.fromEntries(errorCounts));

    // Send to monitoring service (Datadog, New Relic, etc.)
  }
}
```

## Need Help?

If you're experiencing persistent errors or need assistance:

<CardGroup cols={2}>
  <Card title="Check Status Page" icon="chart-line" href="https://status.buena.ai">
    See if there are any known issues
  </Card>

  <Card title="Contact Support" icon="envelope" href="mailto:support@buena.ai">
    Email our support team with error details
  </Card>

  <Card title="Discord Community" icon="discord" href="https://discord.gg/Hb4Y9Rgh6E">
    Get help from other developers
  </Card>

  <Card title="Documentation" icon="book" href="/api-reference/introduction">
    Review the full API reference
  </Card>
</CardGroup>

When contacting support, please include:

* API key prefix (first 8 characters)
* Error response with timestamp
* Request details (endpoint, method, payload)
* Expected vs actual behavior
