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

# Error Handling

> Understanding API error responses and how to handle them

## Error Response Structure

All API errors return a JSON response:

```json theme={null}
{
  "error": {
    "code": "authentication_required",
    "message": "Invalid or missing API key"
  }
}
```

## HTTP Status Codes

### Success Codes (2xx)

| Status             | Description       | When Used            |
| ------------------ | ----------------- | -------------------- |
| **200 OK**         | Request succeeded | Successful GET, POST |
| **201 Created**    | Resource created  | Successful creation  |
| **204 No Content** | Success, no body  | Successful DELETE    |

### Client Error Codes (4xx)

| Status                       | Description                                    |
| ---------------------------- | ---------------------------------------------- |
| **400 Bad Request**          | Malformed request syntax or invalid parameters |
| **401 Unauthorised**         | Missing or invalid API key                     |
| **403 Forbidden**            | Valid API key but insufficient permissions     |
| **404 Not Found**            | Requested resource does not exist              |
| **422 Unprocessable Entity** | Request body validation failed                 |
| **429 Too Many Requests**    | Usage limit exceeded                           |

### Server Error Codes (5xx)

| Status                        | Description                     |
| ----------------------------- | ------------------------------- |
| **500 Internal Server Error** | Unexpected server error         |
| **503 Service Unavailable**   | Service temporarily unavailable |

## Error Handling with the SDK

The SDK returns typed responses that may contain either a success or error response:

```typescript theme={null}
import { SDK } from '@vepler/sdk';

const vepler = new SDK({ apiKey: process.env.VEPLER_API_KEY });

const response = await vepler.property.getV1PropertyLocationIds({
  locationIds: 'p_0x000123456789'
});

// Check for successful response
if (response.propertyListResponse) {
  console.log('Success:', response.propertyListResponse.result);
}

// Check for error response
if (response.errorResponse) {
  console.error('Error:', response.errorResponse.error);
  console.error('Code:', response.errorResponse.code);
}
```

## Error Handling with HTTP

```typescript theme={null}
const response = await fetch('https://api.vepler.com/v1/property/p_0x000123456789', {
  headers: { 'x-api-key': process.env.VEPLER_API_KEY }
});

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

  switch (response.status) {
    case 401:
      console.error('Invalid API key');
      break;
    case 404:
      console.error('Resource not found');
      break;
    case 429:
      console.error('Usage limit exceeded — retry shortly');
      break;
    default:
      console.error('Error:', error);
  }
}
```

## Retry Strategy

Implement exponential backoff for transient errors (429, 5xx):

```typescript theme={null}
async function retryWithBackoff(
  fn: () => Promise<unknown>,
  maxRetries = 3,
  baseDelay = 1000
): Promise<unknown> {
  for (let i = 0; i < maxRetries; i++) {
    try {
      return await fn();
    } catch (error) {
      const err = error as { statusCode?: number };

      // Don't retry client errors (except 429)
      if (err.statusCode && err.statusCode >= 400 && err.statusCode < 500 && err.statusCode !== 429) {
        throw error;
      }

      if (i === maxRetries - 1) throw error;

      const delay = baseDelay * Math.pow(2, i);
      console.log(`Retry ${i + 1}/${maxRetries} after ${delay}ms`);
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

## Best Practices

<AccordionGroup>
  <Accordion title="Always Handle Errors" icon="shield">
    Never assume API calls will succeed:

    ```typescript theme={null}
    const response = await vepler.property.getV1PropertyLocationIds({
      locationIds: id
    });

    if (response.errorResponse) {
      // Handle error
      console.error(response.errorResponse);
      return null;
    }

    return response.propertyListResponse;
    ```
  </Accordion>

  <Accordion title="Use Specific Error Handlers" icon="code-branch">
    Handle different status codes appropriately:

    ```typescript theme={null}
    function handleError(statusCode: number): void {
      switch (statusCode) {
        case 401:
          console.error('Check your API key');
          break;
        case 404:
          console.log('Resource not found');
          break;
        case 429:
          console.log('Slow down — retry shortly');
          break;
        default:
          console.error('Unexpected error:', statusCode);
      }
    }
    ```
  </Accordion>

  <Accordion title="Implement Timeouts" icon="clock">
    Set reasonable timeouts:

    ```typescript theme={null}
    const controller = new AbortController();
    const timeout = setTimeout(() => controller.abort(), 5000);

    try {
      const response = await fetch('https://api.vepler.com/v1/property/health', {
        headers: { 'x-api-key': process.env.VEPLER_API_KEY! },
        signal: controller.signal
      });
    } finally {
      clearTimeout(timeout);
    }
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Usage & Limits" icon="gauge" href="/guides/rate-limiting">
    Understand usage metering
  </Card>

  <Card title="Pagination" icon="list" href="/concepts/pagination">
    Handle paginated responses
  </Card>
</CardGroup>
