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

# Error Handling

> Understand error codes, responses, and troubleshooting strategies for the Mindhunters API

## Error Response Format

All API errors follow a consistent JSON format to help you quickly identify and resolve issues.

```json Standard Error Response theme={null}
{
  "success": false,
  "message": "Human-readable error description",
  "error": {
    "code": "ERROR_CODE",
    "details": "Additional context about the error",
    "field": "fieldName" // Present for validation errors
  }
}
```

<ParamField path="success" type="boolean">
  Always `false` for error responses
</ParamField>

<ParamField path="message" type="string">
  A human-readable description of the error
</ParamField>

<ParamField path="error" type="object">
  Detailed error information

  <Expandable title="properties">
    <ParamField path="code" type="string">
      Machine-readable error code
    </ParamField>

    <ParamField path="details" type="string">
      Additional context or explanation
    </ParamField>

    <ParamField path="field" type="string">
      The specific field that caused the error (validation errors only)
    </ParamField>
  </Expandable>
</ParamField>

## HTTP Status Codes

The Mindhunters API uses standard HTTP status codes to indicate success or failure.

### Success Codes (2xx)

| Status Code | Meaning | Description                   |
| ----------- | ------- | ----------------------------- |
| 200         | OK      | Request succeeded             |
| 201         | Created | Resource successfully created |

### Client Error Codes (4xx)

| Status Code | Meaning              | Description                              |
| ----------- | -------------------- | ---------------------------------------- |
| 400         | Bad Request          | Malformed request or invalid JSON        |
| 401         | Unauthorized         | Missing or invalid authentication token  |
| 403         | Forbidden            | Valid token but insufficient permissions |
| 404         | Not Found            | Resource or endpoint doesn't exist       |
| 422         | Unprocessable Entity | Validation failed on one or more fields  |
| 429         | Too Many Requests    | Rate limit exceeded                      |

### Server Error Codes (5xx)

| Status Code | Meaning               | Description                            |
| ----------- | --------------------- | -------------------------------------- |
| 500         | Internal Server Error | Unexpected server error occurred       |
| 502         | Bad Gateway           | Service temporarily unavailable        |
| 503         | Service Unavailable   | Server overloaded or under maintenance |

## Common Errors

### Authentication Errors

#### 401 Unauthorized - Missing Token

```json theme={null}
{
  "success": false,
  "message": "Authentication required",
  "error": {
    "code": "MISSING_AUTH_TOKEN",
    "details": "No authorization header provided"
  }
}
```

**Solution:** Include the `Authorization: Bearer YOUR_API_TOKEN` header in your request.

<CodeGroup>
  ```bash cURL theme={null}
  curl -X GET https://your-tenant.mindhunters.ai/api/v1/calls \
    -H "Authorization: Bearer YOUR_API_TOKEN"
  ```

  ```javascript JavaScript theme={null}
  const response = await fetch('https://your-tenant.mindhunters.ai/api/v1/calls', {
    headers: {
      'Authorization': `Bearer ${YOUR_API_TOKEN}`
    }
  });
  ```
</CodeGroup>

#### 401 Unauthorized - Invalid Token

```json theme={null}
{
  "success": false,
  "message": "Invalid authentication token",
  "error": {
    "code": "INVALID_AUTH_TOKEN",
    "details": "The provided token is invalid or has been revoked"
  }
}
```

**Solution:** Verify your API token is correct and hasn't been revoked. Generate a new token if necessary.

#### 403 Forbidden - Insufficient Permissions

```json theme={null}
{
  "success": false,
  "message": "Insufficient permissions",
  "error": {
    "code": "FORBIDDEN",
    "details": "Your API token does not have permission to access this resource"
  }
}
```

**Solution:** Ensure your API token has the necessary permissions. Contact your workspace admin.

### Validation Errors

#### 422 Unprocessable Entity - Missing Required Field

```json theme={null}
{
  "success": false,
  "message": "Validation failed",
  "error": {
    "code": "VALIDATION_ERROR",
    "field": "agentId",
    "details": "The agentId field is required"
  }
}
```

**Solution:** Include all required fields in your request body.

#### 422 Unprocessable Entity - Invalid Format

```json theme={null}
{
  "success": false,
  "message": "Validation failed",
  "error": {
    "code": "INVALID_FORMAT",
    "field": "participant.number",
    "details": "Phone number must be in E.164 format (e.g., +1234567890)"
  }
}
```

**Solution:** Ensure phone numbers are in E.164 format (+\[country code]\[number]).

<CodeGroup>
  ```javascript Valid E.164 Format theme={null}
  {
    "participant": {
      "number": "+1234567890"  // ✓ Valid
    }
  }
  ```

  ```javascript Invalid Formats theme={null}
  {
    "participant": {
      "number": "1234567890"   // ✗ Missing +
    }
  }

  {
    "participant": {
      "number": "+1-234-567-890"  // ✗ Contains hyphens
    }
  }
  ```
</CodeGroup>

#### 422 Unprocessable Entity - Invalid UUID

```json theme={null}
{
  "success": false,
  "message": "Validation failed",
  "error": {
    "code": "INVALID_UUID",
    "field": "agentId",
    "details": "agentId must be a valid UUID"
  }
}
```

**Solution:** Ensure UUIDs are in the correct format (e.g., `550e8400-e29b-41d4-a716-446655440000`).

### Resource Errors

#### 404 Not Found - Resource

```json theme={null}
{
  "success": false,
  "message": "Resource not found",
  "error": {
    "code": "RESOURCE_NOT_FOUND",
    "details": "Call with ID '550e8400-e29b-41d4-a716-446655440000' not found"
  }
}
```

**Solution:** Verify the resource ID is correct and the resource exists in your workspace.

#### 404 Not Found - Endpoint

```json theme={null}
{
  "success": false,
  "message": "Endpoint not found",
  "error": {
    "code": "ENDPOINT_NOT_FOUND",
    "details": "The requested endpoint does not exist"
  }
}
```

**Solution:** Check the endpoint URL and HTTP method. Verify you're using the correct API version.

### Rate Limit Errors

#### 429 Too Many Requests

```json theme={null}
{
  "success": false,
  "message": "Rate limit exceeded",
  "error": {
    "code": "RATE_LIMIT_EXCEEDED",
    "details": "You have exceeded the rate limit of 1000 requests per minute",
    "retryAfter": 45
  }
}
```

**Solution:** Implement exponential backoff and retry logic. Wait for the time specified in `retryAfter` (seconds).

<CodeGroup>
  ```javascript Retry with Exponential Backoff theme={null}
  async function makeRequestWithRetry(url, options, maxRetries = 3) {
    for (let attempt = 0; attempt < maxRetries; attempt++) {
      try {
        const response = await fetch(url, options);

        if (response.status === 429) {
          const data = await response.json();
          const retryAfter = data.error.retryAfter || Math.pow(2, attempt);

          console.log(`Rate limited. Retrying after ${retryAfter}s...`);
          await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
          continue;
        }

        return response;
      } catch (error) {
        if (attempt === maxRetries - 1) throw error;
        await new Promise(resolve => setTimeout(resolve, Math.pow(2, attempt) * 1000));
      }
    }
  }
  ```

  ```python Retry with Exponential Backoff theme={null}
  import time
  import requests

  def make_request_with_retry(url, headers, max_retries=3):
      for attempt in range(max_retries):
          try:
              response = requests.get(url, headers=headers)

              if response.status_code == 429:
                  data = response.json()
                  retry_after = data.get('error', {}).get('retryAfter', 2 ** attempt)

                  print(f"Rate limited. Retrying after {retry_after}s...")
                  time.sleep(retry_after)
                  continue

              return response

          except Exception as e:
              if attempt == max_retries - 1:
                  raise e
              time.sleep(2 ** attempt)
  ```
</CodeGroup>

### Server Errors

#### 500 Internal Server Error

```json theme={null}
{
  "success": false,
  "message": "An unexpected error occurred",
  "error": {
    "code": "INTERNAL_SERVER_ERROR",
    "details": "Please try again later or contact support if the issue persists"
  }
}
```

**Solution:** This is a temporary server error. Retry the request. If the error persists, contact [support@mindhunters.ai](mailto:support@mindhunters.ai) with the request details.

#### 503 Service Unavailable

```json theme={null}
{
  "success": false,
  "message": "Service temporarily unavailable",
  "error": {
    "code": "SERVICE_UNAVAILABLE",
    "details": "The service is under maintenance or experiencing high load"
  }
}
```

**Solution:** Wait a few minutes and retry. Check the Mindhunters status page for ongoing incidents.

## Error Handling Best Practices

<AccordionGroup>
  <Accordion title="Always check response status" icon="check-double">
    Never assume a request succeeded. Always check the HTTP status code and handle errors appropriately.

    ```javascript theme={null}
    const response = await fetch(url, options);

    if (!response.ok) {
      const error = await response.json();
      console.error('API Error:', error.message);
      // Handle error appropriately
    }
    ```
  </Accordion>

  <Accordion title="Implement retry logic" icon="arrows-rotate">
    Implement exponential backoff for transient errors (5xx, 429). Don't retry client errors (4xx) except after fixing the issue.

    **Retry:** 429, 500, 502, 503
    **Don't retry:** 400, 401, 403, 404, 422
  </Accordion>

  <Accordion title="Log errors with context" icon="file-lines">
    Log errors with request IDs, timestamps, and relevant context for debugging.

    ```javascript theme={null}
    console.error('API Error', {
      timestamp: new Date().toISOString(),
      endpoint: url,
      status: response.status,
      error: errorData
    });
    ```
  </Accordion>

  <Accordion title="Validate before sending" icon="shield-check">
    Validate request data on the client side before sending to reduce validation errors.

    ```javascript theme={null}
    function validatePhoneNumber(number) {
      const e164Regex = /^\+[1-9]\d{1,14}$/;
      if (!e164Regex.test(number)) {
        throw new Error('Invalid phone number format');
      }
      return true;
    }
    ```
  </Accordion>

  <Accordion title="Handle errors gracefully" icon="hand-holding-heart">
    Provide user-friendly error messages instead of exposing technical details.

    ```javascript theme={null}
    try {
      await initiateCall(phoneNumber);
    } catch (error) {
      if (error.status === 422) {
        showUserMessage('Please check the phone number format');
      } else if (error.status === 429) {
        showUserMessage('Too many requests. Please try again in a moment');
      } else {
        showUserMessage('An error occurred. Please try again');
      }
    }
    ```
  </Accordion>

  <Accordion title="Monitor error rates" icon="chart-line">
    Track error rates and patterns in your monitoring system. Set up alerts for unusual error spikes.
  </Accordion>
</AccordionGroup>

## Complete Error Handling Example

Here's a comprehensive example with proper error handling:

<CodeGroup>
  ```javascript Complete Example - JavaScript theme={null}
  class MindhuntersAPIClient {
    constructor(tenant, apiToken) {
      this.baseUrl = `https://${tenant}.mindhunters.ai/api/v1`;
      this.apiToken = apiToken;
    }

    async makeRequest(endpoint, options = {}) {
      const url = `${this.baseUrl}${endpoint}`;
      const defaultOptions = {
        headers: {
          'Authorization': `Bearer ${this.apiToken}`,
          'Content-Type': 'application/json',
          ...options.headers
        }
      };

      const requestOptions = { ...defaultOptions, ...options };

      try {
        const response = await fetch(url, requestOptions);

        // Handle successful responses
        if (response.ok) {
          return await response.json();
        }

        // Parse error response
        const errorData = await response.json();

        // Handle specific error types
        switch (response.status) {
          case 400:
            throw new Error(`Bad Request: ${errorData.message}`);

          case 401:
            throw new Error('Authentication failed. Please check your API token.');

          case 403:
            throw new Error('Permission denied. Insufficient permissions.');

          case 404:
            throw new Error(`Not found: ${errorData.message}`);

          case 422:
            const field = errorData.error?.field || 'unknown';
            throw new Error(`Validation error in ${field}: ${errorData.message}`);

          case 429:
            const retryAfter = errorData.error?.retryAfter || 60;
            throw new Error(`Rate limit exceeded. Retry after ${retryAfter}s`);

          case 500:
          case 502:
          case 503:
            throw new Error('Server error. Please try again later.');

          default:
            throw new Error(`API Error: ${errorData.message}`);
        }

      } catch (error) {
        if (error instanceof TypeError) {
          throw new Error('Network error. Please check your connection.');
        }
        throw error;
      }
    }

    async initiateCall(agentId, phoneNumber, options = {}) {
      // Validate phone number format
      if (!/^\+[1-9]\d{1,14}$/.test(phoneNumber)) {
        throw new Error('Phone number must be in E.164 format (e.g., +1234567890)');
      }

      return await this.makeRequest('/call', {
        method: 'POST',
        body: JSON.stringify({
          agentId,
          participant: { number: phoneNumber },
          ...options
        })
      });
    }
  }

  // Usage
  const client = new MindhuntersAPIClient('your-tenant', 'YOUR_API_TOKEN');

  try {
    const result = await client.initiateCall(
      '550e8400-e29b-41d4-a716-446655440000',
      '+1234567890'
    );
    console.log('Call initiated:', result.data.id);
  } catch (error) {
    console.error('Failed to initiate call:', error.message);
  }
  ```

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

  class MindhuntersAPIClient:
      def __init__(self, tenant: str, api_token: str):
          self.base_url = f"https://{tenant}.mindhunters.ai/api/v1"
          self.api_token = api_token
          self.headers = {
              "Authorization": f"Bearer {api_token}",
              "Content-Type": "application/json"
          }

      def make_request(
          self,
          endpoint: str,
          method: str = "GET",
          data: Optional[Dict[str, Any]] = None,
          max_retries: int = 3
      ) -> Dict[str, Any]:
          url = f"{self.base_url}{endpoint}"

          for attempt in range(max_retries):
              try:
                  if method == "GET":
                      response = requests.get(url, headers=self.headers)
                  elif method == "POST":
                      response = requests.post(url, headers=self.headers, json=data)
                  elif method == "PATCH":
                      response = requests.patch(url, headers=self.headers, json=data)
                  elif method == "DELETE":
                      response = requests.delete(url, headers=self.headers)

                  # Handle successful responses
                  if response.ok:
                      return response.json()

                  # Parse error response
                  error_data = response.json()

                  # Handle specific error types
                  if response.status_code == 400:
                      raise ValueError(f"Bad Request: {error_data['message']}")

                  elif response.status_code == 401:
                      raise PermissionError("Authentication failed. Check your API token.")

                  elif response.status_code == 403:
                      raise PermissionError("Permission denied. Insufficient permissions.")

                  elif response.status_code == 404:
                      raise ValueError(f"Not found: {error_data['message']}")

                  elif response.status_code == 422:
                      field = error_data.get('error', {}).get('field', 'unknown')
                      raise ValueError(f"Validation error in {field}: {error_data['message']}")

                  elif response.status_code == 429:
                      retry_after = error_data.get('error', {}).get('retryAfter', 60)
                      if attempt < max_retries - 1:
                          print(f"Rate limited. Retrying after {retry_after}s...")
                          time.sleep(retry_after)
                          continue
                      raise Exception(f"Rate limit exceeded. Retry after {retry_after}s")

                  elif response.status_code >= 500:
                      if attempt < max_retries - 1:
                          wait_time = 2 ** attempt
                          print(f"Server error. Retrying in {wait_time}s...")
                          time.sleep(wait_time)
                          continue
                      raise Exception("Server error. Please try again later.")

                  else:
                      raise Exception(f"API Error: {error_data['message']}")

              except requests.exceptions.ConnectionError:
                  raise Exception("Network error. Please check your connection.")

              except requests.exceptions.Timeout:
                  raise Exception("Request timeout. Please try again.")

      def initiate_call(
          self,
          agent_id: str,
          phone_number: str,
          options: Optional[Dict[str, Any]] = None
      ) -> Dict[str, Any]:
          # Validate phone number format
          import re
          if not re.match(r'^\+[1-9]\d{1,14}$', phone_number):
              raise ValueError("Phone number must be in E.164 format (e.g., +1234567890)")

          data = {
              "agentId": agent_id,
              "participant": {"number": phone_number}
          }

          if options:
              data.update(options)

          return self.make_request("/call", method="POST", data=data)

  # Usage
  client = MindhuntersAPIClient('your-tenant', 'YOUR_API_TOKEN')

  try:
      result = client.initiate_call(
          '550e8400-e29b-41d4-a716-446655440000',
          '+1234567890'
      )
      print(f"Call initiated: {result['data']['id']}")
  except Exception as e:
      print(f"Failed to initiate call: {e}")
  ```
</CodeGroup>

## Troubleshooting Guide

### Quick Diagnostics

<Steps>
  <Step title="Check authentication">
    Verify your API token is correct and hasn't been revoked. Test with a simple GET request.
  </Step>

  <Step title="Validate request format">
    Ensure your request body is valid JSON and includes all required fields.
  </Step>

  <Step title="Check tenant/subdomain">
    Verify you're using the correct tenant in your base URL.
  </Step>

  <Step title="Review API logs">
    Check the [Monitoring](/monitoring) dashboard for detailed error information.
  </Step>

  <Step title="Test with cURL">
    Isolate the issue by testing with a simple cURL command.
  </Step>
</Steps>

### Common Issues and Solutions

| Issue               | Possible Cause                                | Solution                                                 |
| ------------------- | --------------------------------------------- | -------------------------------------------------------- |
| CORS errors         | Calling API from browser without proper setup | Use server-side API calls or configure CORS in dashboard |
| Timeout errors      | Slow network or server overload               | Implement retry logic with exponential backoff           |
| Invalid JSON        | Malformed request body                        | Validate JSON before sending, use `JSON.stringify()`     |
| Wrong content-type  | Missing or incorrect Content-Type header      | Set `Content-Type: application/json`                     |
| Inconsistent errors | Network instability                           | Check network connection, use retry logic                |

## Getting Support

If you continue to experience errors after troubleshooting:

<CardGroup cols={2}>
  <Card title="Check API Logs" icon="magnifying-glass" href="/monitoring">
    Review detailed logs in your dashboard
  </Card>

  <Card title="Email Support" icon="envelope">
    Contact [support@mindhunters.ai](mailto:support@mindhunters.ai) with request details and log IDs
  </Card>

  <Card title="Documentation" icon="book" href="/api-reference">
    Review endpoint-specific documentation
  </Card>

  <Card title="Status Page" icon="circle-check">
    Check status.mindhunters.ai for ongoing incidents
  </Card>
</CardGroup>

### Information to Include

When contacting support, please provide:

* **Request ID** from the error response or logs
* **Timestamp** when the error occurred
* **Endpoint** you were calling
* **Request payload** (sanitized - remove sensitive data)
* **Error response** received
* **Expected behavior**

## Next Steps

<CardGroup cols={2}>
  <Card title="Monitoring" icon="chart-line" href="/monitoring">
    Learn to track and debug API issues
  </Card>

  <Card title="API Reference" icon="code" href="/api-reference">
    Explore all available endpoints
  </Card>

  <Card title="Best Practices" icon="lightbulb" href="/quickstart">
    Follow our quickstart guide
  </Card>

  <Card title="Webhooks" icon="webhook" href="/webhooks">
    Set up event notifications
  </Card>
</CardGroup>
