Skip to main content
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:
{
  "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

FieldDescription
errorAlways true for error responses
codeMachine-readable error code
messageHuman-readable error description
versionAPI version
timestampISO 8601 timestamp of the error
detailsAdditional context (optional)

HTTP Status Codes

2xx Success

  • 200 OK - Request succeeded - 201 Created - Resource created - 204 No Content - Request succeeded, no content

4xx Client Errors

  • 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

5xx Server Errors

  • 500 Internal Server Error - Server issue - 502 Bad Gateway - Upstream error - 503 Service Unavailable - Temporary unavailability

Common Error Codes

Authentication Errors

UNAUTHORIZED (401)

{
  "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)

{
  "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)

{
  "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)

{
  "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)

{
  "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)

{
  "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)

{
  "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)

{
  "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)

{
  "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

Always check the HTTP status code before parsing the response:
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;
  }
}
Different errors require different handling strategies:
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;
  }
}
Retry transient errors with exponential backoff:
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));
    }
  }
}
Log errors with appropriate detail levels:
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);
}

Language-Specific Examples

JavaScript/TypeScript

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

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

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:

Check Status Page

See if there are any known issues

Contact Support

Email our support team with error details

Discord Community

Get help from other developers

Documentation

Review the full API reference
When contacting support, please include:
  • API key prefix (first 8 characters)
  • Error response with timestamp
  • Request details (endpoint, method, payload)
  • Expected vs actual behavior