Skip to main content

Error Response Format

All Vouch API errors follow a consistent format:
{
  "success": false,
  "error": {
    "code": "ERROR_CODE",
    "message": "Human-readable error message",
    "details": {} // Optional additional context
  }
}

HTTP Status Codes

StatusMeaningWhen It Occurs
400Bad RequestInvalid request parameters
401UnauthorizedInvalid or missing API key
403ForbiddenAPI key lacks permission
402Payment RequiredQuota exceeded
429Too Many RequestsRate limit exceeded
500Internal Server ErrorServer error

Error Codes Reference

Authentication Errors (401)

{
  "success": false,
  "error": {
    "code": "UNAUTHORIZED",
    "message": "Invalid API key"
  }
}
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

{
  "success": false,
  "error": {
    "code": "INVALID_KEY_TYPE",
    "message": "Server keys cannot be used in browsers"
  }
}
Cause: Attempting to use server key from browser Solution: Use client key for browser/mobile applications

Request Errors (400)

{
  "success": false,
  "error": {
    "code": "INVALID_EMAIL",
    "message": "Email address is required"
  }
}
Cause: Email parameter missing or empty Solution: Include valid email in request body
{
  "success": false,
  "error": {
    "code": "INVALID_REQUEST",
    "message": "Request body must be valid JSON"
  }
}
Cause: Malformed JSON in request body Solution: Ensure request body is valid JSON
{
  "success": false,
  "error": {
    "code": "MISSING_PROJECT_ID",
    "message": "X-Project-Id header is required"
  }
}
Cause: Missing X-Project-Id header Solution: Include X-Project-Id header in all requests

Permission Errors (403)

{
  "success": false,
  "error": {
    "code": "DOMAIN_NOT_ALLOWED",
    "message": "Origin 'https://example.com' not in allowed domains"
  }
}
Cause: Client key used from unauthorized domain Solution: Add domain to allowed list in dashboard
{
  "success": false,
  "error": {
    "code": "PROJECT_NOT_FOUND",
    "message": "Project not found or API key lacks access"
  }
}
Cause: Project ID invalid or API key doesn’t have access Solution: Verify project ID and API key match

Quota Errors (402)

{
  "success": false,
  "error": {
    "code": "QUOTA_EXCEEDED",
    "message": "Monthly validation quota exceeded",
    "details": {
      "limit": 10000,
      "used": 10000,
      "remaining": 0,
      "resetAt": "2024-02-01T00:00:00Z"
    }
  }
}
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)

{
  "success": false,
  "error": {
    "code": "RATE_LIMITED",
    "message": "Too many requests. Please try again later.",
    "details": {
      "limit": 5000,
      "window": "1 hour",
      "retryAfter": 3600
    }
  }
}
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)

{
  "success": false,
  "error": {
    "code": "INTERNAL_ERROR",
    "message": "An internal error occurred. Please try again."
  }
}
Cause: Unexpected server error Solution:
  • Retry with exponential backoff
  • Contact support if persistent

Handling Errors

  • JavaScript
  • Python
  • Go
try {
  const result = await vouch.validate(email);

  if (!result.success) {
    switch (result.error.code) {
      case 'UNAUTHORIZED':
        console.error('Invalid API key');
        break;

      case 'QUOTA_EXCEEDED':
        console.error('Quota exceeded. Upgrade plan.');
        break;

      case 'RATE_LIMITED':
        // Retry after specified time
        const retryAfter = result.error.details.retryAfter;
        await sleep(retryAfter * 1000);
        return await vouch.validate(email);

      case 'DOMAIN_NOT_ALLOWED':
        console.error('Add domain to allowed list');
        break;

      default:
        console.error('Unknown error:', result.error);
    }
  }
} catch (error) {
  console.error('Request failed:', error);
}

Retry Logic

Implement exponential backoff for rate limits and server errors:
async function validateWithRetry(email, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    try {
      const result = await vouch.validate(email);

      if (!result.success && result.error.code === 'RATE_LIMITED') {
        const retryAfter = result.error.details?.retryAfter || Math.pow(2, i) * 1000;
        await sleep(retryAfter);
        continue;
      }

      return result;
    } catch (error) {
      if (i === maxRetries - 1) throw error;
      await sleep(Math.pow(2, i) * 1000);
    }
  }
}

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:
console.error('Validation failed', {
  email: email,
  errorCode: result.error.code,
  errorMessage: result.error.message,
  projectId: projectId,
  timestamp: new Date().toISOString()
});

Best Practices

const result = await vouch.validate(email);

if (!result.success) {
  // Handle error
  console.error(result.error);
  return;
}

// Process successful result
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)
Don’t expose internal error codes to users:
// Good
if (error.code === 'INVALID_EMAIL') {
  showError('Please enter a valid email address');
}

// Bad
showError(`Error: ${error.code} - ${error.message}`);
Set up alerts when quota reaches 80%:
if (quotaUsed / quotaLimit > 0.8) {
  alertAdmins('Vouch quota at 80%. Consider upgrading.');
}

Next Steps