Error handling & retries

2 min read

Handle API errors predictably with safe retry strategies.

Every error response follows the same structure and includes a clear error code you can match on programmatically.

Response format

Every error follows the same JSON structure. Match on the code field to handle specific cases in your code:

Error Response
JSON
{
  "success": false,
  "data": null,
  "error": {
    "code": "INSUFFICIENT_CREDITS",
    "message": "Insufficient credits: 0 available, 1 required"
  },
  "metadata": {
    "requestId": "00bc3fa0-348f-4955-a1c1-3c7c91234568",
    "executionTimeMs": 3
  }
}

Note

Always include metadata.requestId when contacting support. It lets us trace your request instantly.

Error reference

Status What to do
422 Check your request body: a required field is missing or malformed. For async endpoints, make sure a webhook URL is configured.
401 Check your API key: it may be missing, invalid, or expired. See Authentication.
402 No credits left. Paid lookups (INSUFFICIENT_CREDITS) and the free /check endpoints (NO_CREDITS) are both blocked until you top up. Purchase more or upgrade your plan.
403 Your key lacks a required permission, or the endpoint requires a paid plan. Upgrade to unlock live enrichment, email discovery, and more.
404 No result found for your query. Some endpoints still charge credits; see Not found pricing.
429 Rate limit reached. Wait and retry with backoff (see below).
451 This person has been removed per GDPR/CCPA. Enrichment is permanently blocked.
503 Our service is temporarily unavailable. Retry with backoff (see below).
504 The lookup took too long and timed out. Retry with backoff (see below).

When to retry

These statuses are safe to retry with exponential backoff:

  • 429 you’ve hit a rate limit. Wait for the reset window and retry.
  • 503 temporary service issue. Retry after a short delay.
  • 504 the lookup timed out before completing. Retry after a short delay.

All other errors require a change to your request or configuration before retrying.

Wait a little longer between each retry to give the server time to recover:

Retry delay
const delay = Math.min(1000 * 2 ** attempt, 15000)
const jitter = Math.floor(Math.random() * 250)
await new Promise((r) => setTimeout(r, delay + jitter))
delay = min(1 * 2 ** attempt, 15)
jitter = random.uniform(0, 0.25)
time.sleep(delay + jitter)

Credits and errors

All error responses (401, 402, 403, 422, 429, 451, 503, 504) cost 0 credits.

The 404 status is the only exception: some endpoints charge credits when the lookup was performed but no result was found. See Not found pricing for the full breakdown.

Previous

Which endpoint should I use?

Next

Rate limits & credits