Skip to main content
Back to Docs

Error Handling

All API errors return a consistent JSON format with an HTTP status code, a success: false flag, and a human-readable error message.

Response Format

{
  "success": false,
  "error": "Human-readable error message"
}

Always check the success field before processing the response data.

Error Codes

400 Bad Request

The request is malformed or missing required parameters.

{
  "success": false,
  "error": "Invalid FIPS code format. Must be 5 digits."
}

Fix: Check the request body and query parameters match the API specification.

401 Unauthorized

Missing or invalid API key.

{
  "success": false,
  "error": "Invalid or missing API key"
}

Fix: Ensure your X-API-Key header contains a valid API key. Keys start with wfc_.

403 Forbidden

Your plan does not include access to this endpoint or feature.

{
  "success": false,
  "error": "Upgrade required. Full ROI analysis requires a paid plan."
}

Fix: Upgrade your plan at /pricing to access premium features.

404 Not Found

The requested resource does not exist.

{
  "success": false,
  "error": "No data found for FIPS code 99999"
}

Fix: Verify the FIPS code or ZIP code is valid and exists in our dataset.

429 Too Many Requests

You have exceeded your rate limit for the current window.

{
  "success": false,
  "error": "Rate limit exceeded. Try again in 60 seconds."
}

Fix: Check X-RateLimit-Reset header for when your window resets. Consider upgrading your plan for higher limits.

500 Internal Server Error

An unexpected error occurred on the server.

{
  "success": false,
  "error": "Internal server error"
}

Fix: Retry with exponential backoff. If persistent, contact support.

Retry Strategy

For 429 and 500 errors, use exponential backoff:

async function fetchWithRetry(url, options, maxRetries = 3) {
  for (let i = 0; i < maxRetries; i++) {
    const res = await fetch(url, options);

    if (res.ok) return res.json();

    if (res.status === 429) {
      const reset = res.headers.get('X-RateLimit-Reset');
      const waitMs = reset
        ? Math.max(0, new Date(reset).getTime() - Date.now())
        : Math.pow(2, i) * 1000;
      await new Promise(r => setTimeout(r, waitMs));
      continue;
    }

    if (res.status >= 500) {
      await new Promise(r => setTimeout(r, Math.pow(2, i) * 1000));
      continue;
    }

    // 4xx errors (except 429) are not retryable
    const error = await res.json();
    throw new Error(error.error || 'Request failed');
  }
  throw new Error('Max retries exceeded');
}

Best Practices

  • Always check the success field before accessing response data.
  • Monitor X-RateLimit-Remaining headers to avoid hitting rate limits.
  • Use exponential backoff for retries -- never retry in a tight loop.
  • Log error responses for debugging. Include the request URL and status code.
  • Handle 403 errors by checking your plan tier -- some endpoints require a paid plan.