Skip to main content

Error Handling

HTTP Status Codes

StatusMeaningYour Action
200SuccessProcess the response
204No Content (pull endpoint)Results still processing. Retry later.
400Bad RequestFix the request payload and resubmit
401UnauthorizedCheck your X-API-KEY header
403ForbiddenYour API key does not have access to this project
404Not FoundInvalid project hash, endpoint path, or expired pull token
429Rate LimitedBack off and respect the Retry-After header
500Internal Server ErrorRetry with exponential backoff
503Service UnavailableRetry after 30 seconds

Error Response Format

All errors return a consistent JSON structure:
{
  "error": "VALIDATION_ERROR",
  "message": "Missing required field: company_name",
  "request_id": "req-a1b2c3d4"
}
FieldDescription
errorMachine-readable error code. Use this for programmatic handling.
messageHuman-readable description. Log it, but do not display to end users.
request_idUnique identifier for the request. Include this in all support requests.
Always log request_id. It allows Zenoo support to trace the exact request through internal systems.

Error Codes

Error CodeHTTP StatusDescription
VALIDATION_ERROR400Missing or invalid required fields
INVALID_JSON400Request body is not valid JSON
UNAUTHORIZED401Missing or invalid API key
FORBIDDEN403API key lacks access to this project
NOT_FOUND404Invalid project hash or endpoint path
TOKEN_EXPIRED404Pull token has expired (30-day lifetime)
RATE_LIMITED429Too many requests. Check Retry-After header.
INTERNAL_ERROR500Unexpected server error
PROVIDER_ERROR502Upstream provider (registry, screening) returned an error
SERVICE_UNAVAILABLE503Service temporarily unavailable

Retry Strategy

Exponential Backoff

For transient errors (5xx, timeouts), retry with increasing delays:
Attempt 1: Immediate
Attempt 2: Wait 5 seconds
Attempt 3: Wait 25 seconds
Attempt 4: Wait 60 seconds
Maximum: 4 attempts
async function callWithRetry(fn, maxRetries = 4) {
  const delays = [0, 5000, 25000, 60000];

  for (let attempt = 0; attempt < maxRetries; attempt++) {
    try {
      const response = await fn();

      if (response.status === 429) {
        const retryAfter = response.headers.get("Retry-After");
        const delay = retryAfter
          ? parseInt(retryAfter) * 1000
          : delays[attempt] * 2;
        await sleep(delay);
        continue;
      }

      if (response.status >= 500) {
        if (attempt < maxRetries - 1) {
          await sleep(delays[attempt]);
          continue;
        }
      }

      return response;
    } catch (error) {
      if (attempt === maxRetries - 1) throw error;
      await sleep(delays[attempt]);
    }
  }
}

function sleep(ms) {
  return new Promise((resolve) => setTimeout(resolve, ms));
}

When NOT to Retry

ErrorWhy
400 Bad RequestYour request is malformed. Fix the payload first.
401 UnauthorizedYour API key is wrong. Retrying will not fix it.
403 ForbiddenYour key lacks permissions. Contact Zenoo support.
404 Not FoundThe resource does not exist. Verify your endpoint URL and project hash.
Never retry 4xx errors automatically. They indicate a problem with your request, not a transient server issue.

Rate Limiting

When you exceed your project’s rate limit, you receive a 429 response. The Retry-After header tells you how many seconds to wait. Always use this value instead of guessing.
{
  "error": "RATE_LIMITED",
  "message": "Rate limit exceeded. Retry after 60 seconds.",
  "request_id": "req-a1b2c3d4"
}
Handling rate limits:
  1. Read the Retry-After header value.
  2. Pause requests for that duration.
  3. Resume. If you hit the limit again, increase your backoff.
For high-volume integrations, implement a request queue. Smooth out bursts rather than sending requests as fast as possible. Monitor your request rate and contact Zenoo if you need higher limits.

Zenoo Internal Error Classification

Zenoo classifies errors from upstream providers into three categories. This determines automatic retry behavior on the server side.
CategoryExamplesRetry Behavior
TransientTimeouts, 5xx from providersAuto-retry with exponential backoff
Permanent4xx, invalid data, entity not foundNo retry. Check fails immediately.
Rate Limited429 from providersExtended backoff (2x multiplier)

Automatic Retry Schedule

For async flows, Zenoo automatically retries transient provider failures on your behalf:
RetryDelayCumulative Wait
1st5 minutes5 minutes
2nd25 minutes30 minutes
3rd125 minutes~2.5 hours
Maximum delay is capped at 240 minutes (4 hours). Rate-limited errors use a 2x multiplier on these delays. After all retries are exhausted:
  • The check is marked as Failed.
  • A check.failed webhook is sent to your endpoint.
  • An API Failure alert is created in the case management system.
You do not need to implement retry logic for provider failures. Zenoo handles it automatically.

Circuit Breaker

Zenoo protects upstream providers with a circuit breaker pattern:
StateBehavior
ClosedNormal operation. Requests flow through to the provider.
OpenProvider is down. Requests fail fast and are queued for retry.
Half-OpenRecovery test. A single request is sent to check if the provider is back.
This is transparent to your integration. You do not need to implement any special handling. When a provider’s circuit breaker opens:
  • Checks for that provider are queued automatically.
  • Other providers continue operating normally.
  • You receive results via webhook once the provider recovers.
From your perspective, the verification simply takes longer to complete.

Timeout Handling

Sync Requests

If your X-SYNC-TIMEOUT is reached before all checks complete:
  • The response may contain partial results.
  • A pull token is included in the response headers for retrieving full results later.
  • Consider increasing the timeout or switching to async mode.

Async Requests

The /init endpoint responds immediately with tokens, so connection timeouts are rare. If you experience them:
  • Check your network connectivity.
  • Verify the base URL and project hash.
  • Contact Zenoo support if the issue persists.

Monitoring Recommendations

  1. Track error rates by endpoint and HTTP status code.
  2. Alert on 5xx spikes. Sustained 5xx errors may indicate a provider outage or Zenoo infrastructure issue.
  3. Monitor webhook delivery. Track delivery failures and retry rates.
  4. Log request_id for every API call. This is essential for debugging with Zenoo support.
  5. Track response times. Latency increases may indicate provider degradation.
  6. Monitor rate limit proximity. Alert when you reach 80% of your limit to avoid hitting it during traffic spikes.

Next Steps