Skip to main content

Error Response Format

All Enrow API errors follow this structure:
{
  "error": "ErrorType",
  "message": "Human-readable error description",
  "status": 400
}

Common Errors

400 — Bad Request

{
  "error": "ValidationError",
  "message": "Either company_domain or company_name is required",
  "status": 400
}
Fix: Check that you’re providing all required parameters for the endpoint.

401 — Unauthorized

{
  "error": "Unauthorized",
  "message": "Invalid or missing API key",
  "status": 401
}
Fix: Verify your API key is correct and included in the x-api-key header (not Authorization).

402 — Insufficient Credits

{
  "error": "InsufficientCredits",
  "message": "Your credit balance is 0. Please upgrade your plan.",
  "status": 402
}
Fix: Check your balance on the Dashboard or via GET /account. Top up credits or upgrade your plan at enrow.io/pricing.

429 — Rate Limit Exceeded

{
  "error": "RateLimitExceeded",
  "message": "Rate limit exceeded",
  "retry_after": 300,
  "status": 429
}
Fix: Wait and retry. See Rate Limits for details on limits per plan.

500 — Internal Server Error

{
  "error": "InternalServerError",
  "message": "An unexpected error occurred",
  "status": 500
}
Fix: Retry the request. If the issue persists, contact api@enrow.io.

Implementing Error Handling

Basic Example

async function findEmail(contact) {
  const response = await fetch('https://api.enrow.io/email/find/single', {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json',
      'x-api-key': process.env.ENROW_API_KEY
    },
    body: JSON.stringify(contact)
  });

  if (!response.ok) {
    const error = await response.json();
    throw new Error(`Enrow API error ${error.status}: ${error.message}`);
  }

  return await response.json();
}

Retry Logic with Exponential Backoff

async function requestWithRetry(fn, maxRetries = 3, baseDelay = 1000) {
  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      return await fn();
    } catch (error) {
      const isLastAttempt = attempt === maxRetries - 1;

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

      if (isLastAttempt) throw error;

      const delay = error.retryAfter
        ? error.retryAfter * 1000
        : baseDelay * Math.pow(2, attempt);

      await new Promise(resolve => setTimeout(resolve, delay));
    }
  }
}

Best Practices

  • Don’t retry 4xx errors (except 429) — fix your request instead
  • Retry 429 errors — respect the retry_after value
  • Retry 5xx errors — with exponential backoff
  • Use webhooks instead of polling to avoid hitting rate limits unnecessarily
  • Log errors with context — include the endpoint, parameters, and timestamp for debugging