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

# Error Codes

> Complete reference for Vouch API error codes

## Error Response Format

Vouch API errors return a simple error message with the appropriate HTTP status code:

```json theme={null}
{
  "error": "Human-readable error message"
}
```

Some errors include additional details:

```json theme={null}
{
  "error": "Rate limit exceeded",
  "retryAfter": 3600
}
```

## HTTP Status Codes

| Status | Meaning               | When It Occurs             |
| ------ | --------------------- | -------------------------- |
| 400    | Bad Request           | Invalid request parameters |
| 401    | Unauthorized          | Invalid or missing API key |
| 403    | Forbidden             | API key lacks permission   |
| 402    | Payment Required      | Quota exceeded             |
| 429    | Too Many Requests     | Rate limit exceeded        |
| 500    | Internal Server Error | Server error               |

## Error Codes Reference

### Authentication Errors (401)

<ResponseExample>
  ```json UNAUTHORIZED theme={null}
  {
    "error": "Invalid API key"
  }
  ```
</ResponseExample>

**Cause:** API key is invalid, expired, or malformed

**Solution:**

* Verify your API key is correct
* Check you're using the right environment (test vs live)
* Regenerate key if compromised

***

<ResponseExample>
  ```json INVALID_KEY_TYPE theme={null}
  {
    "error": "Server keys cannot be used in browsers"
  }
  ```
</ResponseExample>

**Cause:** Attempting to use server key from browser

**Solution:** Use client key for browser/mobile applications

***

### Request Errors (400)

<ResponseExample>
  ```json INVALID_EMAIL theme={null}
  {
    "error": "Email address is required"
  }
  ```
</ResponseExample>

**Cause:** Email parameter missing or empty

**Solution:** Include valid email in request body

***

<ResponseExample>
  ```json INVALID_REQUEST theme={null}
  {
    "error": "Request body must be valid JSON"
  }
  ```
</ResponseExample>

**Cause:** Malformed JSON in request body

**Solution:** Ensure request body is valid JSON

***

<ResponseExample>
  ```json MISSING_PROJECT_ID theme={null}
  {
    "error": "X-Project-Id header is required"
  }
  ```
</ResponseExample>

**Cause:** Missing X-Project-Id header

**Solution:** Include X-Project-Id header in all requests

***

### Permission Errors (403)

<ResponseExample>
  ```json DOMAIN_NOT_ALLOWED theme={null}
  {
    "error": "Origin 'https://example.com' not in allowed domains"
  }
  ```
</ResponseExample>

**Cause:** Client key used from unauthorized domain

**Solution:** Add domain to allowed list in dashboard

***

<ResponseExample>
  ```json PROJECT_NOT_FOUND theme={null}
  {
    "error": "Project not found or API key lacks access"
  }
  ```
</ResponseExample>

**Cause:** Project ID invalid or API key doesn't have access

**Solution:** Verify project ID and API key match

***

### Quota Errors (402)

<ResponseExample>
  ```json QUOTA_EXCEEDED theme={null}
  {
    "error": "Monthly validation quota exceeded",
    "limit": 10000,
    "used": 10000,
    "remaining": 0,
    "resetAt": "2024-02-01T00:00:00Z"
  }
  ```
</ResponseExample>

**Cause:** Monthly validation quota exhausted

**Solution:**

* Upgrade your plan
* Wait for quota reset (1st of month)
* Contact support for quota increase

***

### Rate Limit Errors (429)

<ResponseExample>
  ```json RATE_LIMITED theme={null}
  {
    "error": "Too many requests. Please try again later.",
    "limit": 5000,
    "window": "1 hour",
    "retryAfter": 3600
  }
  ```
</ResponseExample>

**Cause:** Exceeded hourly rate limit

**Solution:**

* Implement exponential backoff
* Respect `retryAfter` value (seconds)
* Use server keys for higher limits (5,000/hr vs 1,000/hr)

***

### Server Errors (500)

<ResponseExample>
  ```json INTERNAL_ERROR theme={null}
  {
    "error": "An internal error occurred. Please try again."
  }
  ```
</ResponseExample>

**Cause:** Unexpected server error

**Solution:**

* Retry with exponential backoff
* Contact support if persistent

***

## Handling Errors

### Recommended Error Handling Pattern

<Tabs>
  <Tab title="JavaScript">
    ```javascript theme={null}
    try {
      const result = await vouch.validate(email);

      if (result.recommendation === 'allow') {
        // Proceed with valid email
        return;
      }

      // Option 1: Use the message field for a user-friendly error
      showError(result.message); // e.g. "Please use a permanent email address, not a temporary one."

      // Option 2: Check specific validations for custom logic
      if (!result.checks.syntax?.pass) {
        showError('Invalid email format');
      } else if (!result.checks.disposable?.pass) {
        showError('Disposable emails are not allowed');
      }
    } catch (error) {
      // Network or API errors
      console.error('Validation failed:', error.message);
    }
    ```
  </Tab>

  <Tab title="Node.js">
    ```javascript theme={null}
    import { Vouch } from '@vouch-in/node';

    const vouch = new Vouch(projectId, serverKey);

    try {
      const result = await vouch.validate(email, {
        ip: request.ip,
        userAgent: request.headers['user-agent'],
      });

      if (result.recommendation !== 'allow') {
        // Option 1: Use the message field directly
        return res.status(400).json({
          error: result.message,
        });

        // Option 2: Check specific validations for custom responses
        if (!result.checks.disposable?.pass) {
          return res.status(400).json({ error: 'Disposable emails not allowed' });
        }
        return res.status(400).json({ error: 'Email validation failed' });
      }

      // Proceed with signup
    } catch (error) {
      console.error('Validation error:', error.message);
      return res.status(500).json({
        error: 'Validation service unavailable',
      });
    }
    ```
  </Tab>

  <Tab title="cURL">
    ```bash theme={null}
    # Check HTTP status code
    response=$(curl -s -w "\n%{http_code}" \
      -X POST https://api.vouch.expert/validate \
      -H "Authorization: Bearer $API_KEY" \
      -H "X-Project-Id: $PROJECT_ID" \
      -H "Content-Type: application/json" \
      -d '{"email": "user@example.com"}')

    status=$(echo "$response" | tail -n1)
    body=$(echo "$response" | head -n-1)

    if [ "$status" -eq 200 ]; then
      echo "Success: $body"
    else
      echo "Error ($status): $body"
    fi
    ```
  </Tab>
</Tabs>

### Retry Logic

Implement exponential backoff for transient errors:

```javascript theme={null}
async function validateWithRetry(email, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const result = await vouch.validate(email);
      return result;
    } catch (error) {
      // Don't retry on client errors
      if (error.message.includes('Invalid email')) {
        throw error;
      }

      // Last attempt, give up
      if (i === maxRetries - 1) {
        throw error;
      }

      // Exponential backoff
      const delay = Math.pow(2, i) * 1000;
      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}
```

## Monitoring Errors

### Response Headers

Check these headers to monitor quota and rate limits:

```
X-Quota-Limit: 10000
X-Quota-Used: 2345
X-Quota-Remaining: 7655
X-RateLimit-Limit: 5000
X-RateLimit-Remaining: 4876
X-RateLimit-Reset: 1699564800
```

### Logging Recommendations

Log errors with context for debugging:

```javascript theme={null}
console.error('Validation failed', {
  email: email,
  errorCode: result.error.code,
  errorMessage: result.error.message,
  projectId: projectId,
  timestamp: new Date().toISOString()
});
```

## Best Practices

<AccordionGroup>
  <Accordion title="Always check the recommendation" icon="check">
    ```javascript theme={null}
    const result = await vouch.validate(email);

    if (result.recommendation !== 'allow') {
      // Use the message field for a user-friendly error
      console.log(result.message);
      return;
    }

    // Proceed with valid email
    ```
  </Accordion>

  <Accordion title="Implement retry logic for transient errors" icon="rotate">
    Retry on:

    * `RATE_LIMITED` (with exponential backoff)
    * `INTERNAL_ERROR` (max 3 retries)

    Don't retry on:

    * `UNAUTHORIZED` (fix API key)
    * `QUOTA_EXCEEDED` (upgrade plan)
    * `INVALID_EMAIL` (invalid input)
  </Accordion>

  <Accordion title="Show user-friendly messages" icon="message">
    Use the `message` field for quick user-facing errors, or check individual validations for custom logic:

    ```javascript theme={null}
    if (result.recommendation !== 'allow') {
      // Option 1: Use the message field directly
      showError(result.message); // e.g. "Please use a permanent email address, not a temporary one."

      // Option 2: Check specific validations for custom messages
      if (!result.checks.syntax?.pass) {
        showError('Please enter a valid email address');
      } else if (!result.checks.disposable?.pass) {
        showError('Disposable emails are not allowed');
      }
    }

    // Bad - exposing internal details
    showError(`Error: ${result.signals.join(', ')}`);
    ```
  </Accordion>

  <Accordion title="Monitor quota proactively" icon="chart-line">
    Set up alerts when quota reaches 80%:

    ```javascript theme={null}
    if (quotaUsed / quotaLimit > 0.8) {
      alertAdmins('Vouch quota at 80%. Consider upgrading.');
    }
    ```
  </Accordion>
</AccordionGroup>

## Next Steps

<CardGroup cols={2}>
  <Card title="Error Handling Guide" icon="shield" href="/guides/error-handling">
    Comprehensive error handling strategies
  </Card>

  <Card title="Rate Limits" icon="gauge" href="/guides/rate-limits">
    Understanding and managing rate limits
  </Card>

  <Card title="Best Practices" icon="star" href="/guides/best-practices">
    Production deployment tips
  </Card>

  <Card title="Dashboard" icon="chart-line" href="https://vouch.expert">
    Monitor quota and usage
  </Card>
</CardGroup>
