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

# Error Handling

> Learn how to handle API errors gracefully

# Error Handling

The My Virtual Office API uses standard HTTP status codes to indicate the success or failure of requests. This guide explains the error responses you may encounter and how to handle them.

## Error Response Format

All error responses follow a consistent JSON format:

```json theme={null}
{
  "error": "Error Type",
  "message": "Human-readable description of what went wrong"
}
```

## HTTP Status Codes

### Success Codes

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

### Client Error Codes

| Code | Description                                                              |
| ---- | ------------------------------------------------------------------------ |
| 400  | Bad Request - Invalid request format or missing required fields          |
| 401  | Unauthorized - Missing or invalid API key                                |
| 403  | Forbidden - Valid API key but insufficient permissions or limits reached |
| 404  | Not Found - Resource doesn't exist                                       |
| 409  | Conflict - Resource already exists (e.g., duplicate email)               |
| 429  | Too Many Requests - Rate limit exceeded                                  |

### Server Error Codes

| Code | Description                                             |
| ---- | ------------------------------------------------------- |
| 500  | Internal Server Error - Something went wrong on our end |
| 503  | Service Unavailable - API temporarily unavailable       |

## Common Errors and Solutions

### Authentication Errors (401)

<Accordion title="API key is missing">
  ```json theme={null}
  {
    "error": "Unauthorized",
    "message": "API key is required. Provide it via X-API-Key header or Authorization Bearer token."
  }
  ```

  **Solution:** Include your API key in the request headers:

  ```bash theme={null}
  -H "X-API-Key: sk_live_your_api_key_here"
  ```
</Accordion>

<Accordion title="Invalid API key">
  ```json theme={null}
  {
    "error": "Unauthorized",
    "message": "Invalid API key"
  }
  ```

  **Solution:** Verify your API key is correct. Generate a new one from [Settings > API Keys](https://app.my-virtual-office.com/dashboard/settings/api-keys) if needed.
</Accordion>

<Accordion title="API key revoked">
  ```json theme={null}
  {
    "error": "Unauthorized",
    "message": "API key has been revoked"
  }
  ```

  **Solution:** This API key has been disabled. Generate a new one from your dashboard.
</Accordion>

<Accordion title="API key expired">
  ```json theme={null}
  {
    "error": "Unauthorized",
    "message": "API key has expired"
  }
  ```

  **Solution:** This API key has passed its expiration date. Generate a new one from your dashboard.
</Accordion>

### Validation Errors (400)

<Accordion title="Missing required field">
  ```json theme={null}
  {
    "error": "Bad Request",
    "message": "body must have required property 'email'"
  }
  ```

  **Solution:** Ensure all required fields are included in your request body.
</Accordion>

<Accordion title="Invalid email format">
  ```json theme={null}
  {
    "error": "Bad Request",
    "message": "body/email must match format \"email\""
  }
  ```

  **Solution:** Provide a valid email address in the correct format.
</Accordion>

### Business Logic Errors (403)

<Accordion title="Customer limit reached">
  ```json theme={null}
  {
    "error": "Forbidden",
    "message": "Customer limit reached. Your plan allows 10 customers."
  }
  ```

  **Solution:** Upgrade your subscription to add more customers, or remove existing customers you no longer need.
</Accordion>

### Conflict Errors (409)

<Accordion title="Duplicate email">
  ```json theme={null}
  {
    "error": "Conflict",
    "message": "A customer with this email already exists"
  }
  ```

  **Solution:** Each customer must have a unique email address within your account. Use a different email or update the existing customer.
</Accordion>

## Best Practices

### 1. Always Check Status Codes

```javascript theme={null}
const response = await fetch('https://app-api.my-virtual-office.com/api/customers', {
  method: 'POST',
  headers: {
    'X-API-Key': apiKey,
    'Content-Type': 'application/json',
  },
  body: JSON.stringify(customerData),
});

if (!response.ok) {
  const error = await response.json();

  switch (response.status) {
    case 401:
      // Handle authentication error
      console.error('Authentication failed:', error.message);
      break;
    case 403:
      // Handle limit reached
      console.error('Limit reached:', error.message);
      break;
    case 409:
      // Handle duplicate
      console.error('Customer already exists:', error.message);
      break;
    default:
      console.error('API error:', error.message);
  }
  return;
}

const customer = await response.json();
```

### 2. Implement Retry Logic

For transient errors (5xx), implement retry with exponential backoff:

```javascript theme={null}
async function createCustomerWithRetry(data, maxRetries = 3) {
  for (let attempt = 1; attempt <= maxRetries; attempt++) {
    try {
      const response = await fetch('https://app-api.my-virtual-office.com/api/customers', {
        method: 'POST',
        headers: {
          'X-API-Key': apiKey,
          'Content-Type': 'application/json',
        },
        body: JSON.stringify(data),
      });

      if (response.status >= 500) {
        throw new Error(`Server error: ${response.status}`);
      }

      return await response.json();
    } catch (error) {
      if (attempt === maxRetries) throw error;

      // Exponential backoff: 1s, 2s, 4s
      const delay = Math.pow(2, attempt - 1) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

### 3. Log Errors for Debugging

Keep detailed logs of API errors to help with debugging:

```javascript theme={null}
if (!response.ok) {
  const error = await response.json();
  console.error({
    timestamp: new Date().toISOString(),
    endpoint: '/api/customers',
    method: 'POST',
    status: response.status,
    error: error.error,
    message: error.message,
    requestData: customerData,
  });
}
```

### 4. Handle Rate Limiting

If you receive a 429 error, wait before retrying:

```javascript theme={null}
if (response.status === 429) {
  const retryAfter = response.headers.get('Retry-After') || 60;
  await new Promise(resolve => setTimeout(resolve, retryAfter * 1000));
  // Retry the request
}
```

## Need Help?

If you're encountering errors that you can't resolve, please contact our support team at [hello@my-virtual-office.com](mailto:hello@my-virtual-office.com) with:

* The endpoint you're calling
* The request body (with sensitive data removed)
* The full error response
* Your account email
