Skip to main content

Error Handling

The Voicy API uses conventional HTTP status codes to indicate success or failure of requests.

Error Response Format

All error responses follow this format:
{
  "error": "Description of what went wrong"
}

HTTP Status Codes

Success Codes

CodeMeaningWhen Used
200OKSuccessful GET, POST, PATCH requests
201CreatedSuccessful resource creation (create-phone-call)
204No ContentSuccessful DELETE requests

Client Error Codes

CodeMeaningCommon Causes
400Bad RequestInvalid JSON, missing required fields, invalid phone number format
401UnauthorizedInvalid API key, expired token, missing Authorization header
403ForbiddenAPI key doesn’t have access to the requested resource
404Not FoundCall ID doesn’t exist or belongs to another account
422Unprocessable EntityRequest is valid but cannot be processed
429Too Many RequestsRate limit exceeded

Server Error Codes

CodeMeaningWhat To Do
500Internal Server ErrorRetry with exponential backoff, contact support if persistent
502Bad GatewayTemporary issue, retry after a few seconds
503Service UnavailableService is temporarily down, retry later

Common Errors

Authentication Errors

// Missing Authorization header
{
  "error": "Missing authorization"
}

// Invalid API key
{
  "error": "Invalid API key"
}

// Expired JWT token (dashboard)
{
  "error": "Invalid or expired token"
}

Validation Errors

// Invalid phone number format
{
  "error": "Invalid phone number format. Use E.164 (e.g. +11234567890)"
}

// Missing required field
{
  "error": "to_number is required"
}

// Phone number not in your account
{
  "error": "Phone number not found or not assigned to your account"
}

Access Errors

// Trying to access another account's data
{
  "error": "Access denied"
}

// Resource doesn't exist
{
  "error": "Call not found"
}

Best Practices

Retry Logic

Implement exponential backoff for transient errors:
async function callWithRetry(fn, maxRetries = 3) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      if (error.status >= 500 && attempt < maxRetries - 1) {
        // Wait 2^attempt seconds before retrying
        await new Promise(r => setTimeout(r, 1000 * Math.pow(2, attempt)));
        continue;
      }
      throw error;
    }
  }
}

Error Logging

Log errors with context for debugging:
try {
  const call = await createPhoneCall(fromNumber, toNumber);
} catch (error) {
  console.error('Failed to create call', {
    fromNumber,
    toNumber,
    status: error.status,
    message: error.message,
  });
  throw error;
}

User-Friendly Messages

Map API errors to user-friendly messages:
function getUserMessage(error) {
  switch (error.message) {
    case 'Invalid phone number format. Use E.164 (e.g. +11234567890)':
      return 'Please enter a valid phone number with country code (e.g., +1 555 123 4567)';
    case 'Phone number not found or not assigned to your account':
      return 'This phone number is not available. Please contact support.';
    default:
      return 'Something went wrong. Please try again.';
  }
}