SDKs // TypeScript // Guides
Errors and retries
Last verified
Handle typed errors and automatic retries in the Reverse Contact TypeScript SDK, and reuse idempotency keys for Find Email, Verify Email and Find Phone.
Catch SDK errors by class and preserve the request id when reporting an API failure.
Error classes and retry policy
Every SDK error extends ReverseContactError. Errors returned by the API extend APIError and include status, code, message, details, requestId, headers and body.
| HTTP status | Error class |
|---|---|
400 | BadRequestError |
401 | AuthenticationError |
402 | InsufficientCreditsError |
403 | PermissionDeniedError |
404 | NotFoundError (a lookup with no match returns null instead) |
409 | ConflictError |
410 | GoneError |
422 | UnprocessableEntityError |
429 | RateLimitError, or DailyLimitError for a daily limit |
451 | UnavailableForLegalReasonsError |
5xx | InternalServerError |
Any status with KEY_CREDIT_LIMIT_REACHED | KeyCreditLimitError |
A network failure raises APIConnectionError. An attempt that times out raises APITimeoutError, a subclass of APIConnectionError.
The SDK retries a request up to 4 times after the first attempt, 5 attempts in total:
- For a
429from the per-minute rate limit, the SDK useserror.details.retryAfteras the delay, or theRetry-Afterheader if that value is missing. Otherwise, the SDK backs off. - For a
500,502,503or504, the SDK uses exponential backoff: 2, 4, 8, then 15 seconds, plus up to 250 milliseconds of jitter. If the response includesRetry-After, the SDK uses that delay instead. - If the requested wait exceeds 60 seconds, the SDK raises the error at once.
- A network failure or a timed-out attempt is retried on
GETrequests. APOSTis retried only when the connection was never established, so a request the API may already have billed is never sent twice. Find Email, Verify Email and Find Phone are the exception, protected by their idempotency key (see below).
The SDK never retries DailyLimitError (daily limits, DAILY_LIMIT_EXCEEDED and DAILY_EXTRACTION_LIMIT_EXCEEDED), KeyCreditLimitError (an API key credit limit) or InsufficientCreditsError. Other 4xx errors are not retried either, except per-minute 429 rate limits and 409 IDEMPOTENCY_KEY_IN_USE for Find Email, Verify Email and Find Phone.
For a non-retryable error, change the request, key or account, or wait until the next day. Set maxRetries: 0 to turn retries off.
Handle errors
import ReverseContact, { APIError, DailyLimitError, KeyCreditLimitError } from "@reverse-contact/sdk";
const client = new ReverseContact({ apiKey: process.env.RC_API_KEY });
try {
await client.enrich.company({ domain: "acme.com" });
} catch (error) {
if (error instanceof DailyLimitError || error instanceof KeyCreditLimitError) {
// Not retried: pause the work until the limit resets.
console.error("Limit reached:", error.code, "retry after", error.retryAfter, "seconds");
} else if (error instanceof APIError) {
console.error(error.status, error.code, error.message, "request id:", error.requestId);
} else {
throw error;
}
}Error handling & retries lists every error code of the API.
Safe retries on Find Email and Find Phone
Sending the same Find Email, Verify Email or Find Phone request twice would start two jobs, and both can be billed. To prevent duplicate jobs on automatic retries, contact.findEmail, contact.verifyEmail and contact.findPhone send an Idempotency-Key header with a new UUID on each call. The SDK reuses that key on every automatic retry of the call. For 24 hours, repeating the same key and body returns the first response without starting or billing another lookup.
To retry safely after your process restarts, choose the key yourself, store it with the request, and pass it as idempotencyKey. job.replayed is true when the API returned the first response again.
Idempotency key
import ReverseContact from "@reverse-contact/sdk";
const client = new ReverseContact({ apiKey: process.env.RC_API_KEY });
const job = await client.contact.findEmail(
{ fullName: "Jane Doe", companyDomain: "acme.com", emailType: "any" },
{ idempotencyKey: "crm-contact-4821-email" }
);
console.log(job.id, job.replayed ? "first response returned again" : "new lookup");
const done = await job.wait();
for (const email of done.data.result ?? []) console.log(email.value, email.type);Use 1 to 255 printable ASCII characters without spaces, and a new key for each new lookup. If the key is empty, longer than 255 characters, or contains a space or non-ASCII character, the SDK raises ReverseContactError before sending a request.
The SDK retries 409 IDEMPOTENCY_KEY_IN_USE after the delay in Retry-After. A 422 IDEMPOTENCY_KEY_REUSED (same key, different body) and a 400 INVALID_IDEMPOTENCY_KEY are not retried. After 24 hours, the same key can start and bill a new lookup. To read a job you already started, call client.jobs.wait(id).
List creation and Bulk submission also generate keys. List imports generate an operationId. See Lists and Bulk enrichment.
Local validation and job errors
ReverseContactError also reports invalid SDK options, missing search budgets, repeated pagination cursors and malformed webhook envelopes. JobTimeoutError reports an expired wait deadline. JobFailedError reports a failed live-fetch or contact job from job.wait() or client.jobs.wait(). See Async jobs and Timeouts and cancellation.
Return to the TypeScript SDK overview.
FAQ
Which requests does the TypeScript SDK retry automatically?
The SDK retries per-minute rate limits and HTTP 500, 502, 503 and 504 up to 4 times after the initial attempt. Contact requests also retry HTTP 409 IDEMPOTENCY_KEY_IN_USE.
Does the SDK retry daily or API key credit limits?
The SDK does not retry DailyLimitError, KeyCreditLimitError or InsufficientCreditsError. Change the request or account limits, or wait for the relevant reset.
How do I retry Find Email safely after a restart?
Persist the request body and an idempotencyKey, then reuse both within 24 hours. For a job id already saved, call client.jobs.wait() to read the existing job.
How do I disable automatic SDK retries?
Set maxRetries: 0 on the client or on an individual request. Wait helpers use their own polling options, described in the Async jobs guide.