Skip to content

MaintenanceThe former company search endpoint goes into maintenance on November 9Migration guide

SDKs // TypeScript // Guides

Lists and Bulk enrichment

Last verified

Create persistent Lists or enrich up to 25,000 people with the TypeScript SDK, follow import operations and Bulk jobs, and download CSV results.

Save people in a List for ongoing work, or run a Bulk job when you need a results file.

Enrich people in bulk

From version 0.2.0, client.lists manages your Lists and client.bulk runs Bulk enrichment jobs.

Use bulk.enrichPersons to start a job of up to 25,000 people. Then call bulk.wait to wait until the job is completed, cancelled, failed or paused.

Once the job is completed or cancelled, bulk.results returns the results CSV as text without a byte order mark. Prepend "\uFEFF" when you save the file so a spreadsheet opens accented names correctly.

The SDK sends an Idempotency-Key with each new job and generates one if you don't supply it. The SDK reuses that key on its retries, so a retried request never creates a second job.

TypeScript SDK

Bulk enrichment

import { writeFile } from "node:fs/promises";
import ReverseContact from "@reverse-contact/sdk";

const client = new ReverseContact({ apiKey: process.env.RC_API_KEY });

const created = await client.bulk.enrichPersons({
  name: "CRM export, November",
  items: [
    { linkedinUrl: "https://social.com/in/janedoe", externalId: "crm-001" },
    { firstName: "John", lastName: "Smith", companyDomain: "acme.com", externalId: "crm-002" }
  ],
  families: ["profile", "contact_email"]
});
const jobId = created.data.job.id;

const job = await client.bulk.wait(jobId);
if (job.data.links.results) {
  await writeFile("results.csv", "\uFEFF" + (await client.bulk.results(jobId)));
}
console.log(job.data.status, "credits:", job.data.credits.used);

Read the results as they come

From version 0.3.0, you can use the results before the job settles. bulk.iterateRows yields them one at a time, in the order sent, as soon as each one is ready. While the next item runs, it waits out the Retry-After of the API. It ends with the job, or when the job is paused: read on later with bulk.rows and the last cursor. A cancelled job first finishes the items it had started, within the hour. bulk.rows reads one page (cursor, limit up to 100), with the job status in extras.status. Each item is a JobResultLine, a type the SDK exports. bulk.results(jobId, { format: "ndjson" }) returns the results file as NDJSON, one JobResultLine per line. The client.bulk reference documents each method.

TypeScript

Results as they come

for await (const item of client.bulk.iterateRows(jobId)) {
  console.log(item.row, item.input.externalId, item.status, item.creditsConsumed);
}

// Or the whole file once the job settles, one JSON object per line:
const ndjson = await client.bulk.results(jobId, { format: "ndjson" });
const items = ndjson.split("\n").filter(Boolean).map((line) => JSON.parse(line));

Keep members in a List

A List keeps its members. Call lists.importSignals to start an import, then lists.operations.wait to wait until clientAction is done, resume or reconcile. The wait method returns the operation so your code can decide what to do next.

If you don't supply them, lists.create generates an Idempotency-Key and lists.importSignals generates an operationId. Pass your own operationId to resume a paused import after a restart.

TypeScript SDK

Lists

const list = await client.lists.create({ name: "Prospects", entity: "persons" });
const listId = list.data.id;

const imported = await client.lists.importSignals(listId, {
  signals: [{ email: "jane@acme.com", externalId: "crm-001" }],
  families: ["contact_email"],
  maxCredits: 100
});
const operation = await client.lists.operations.wait(listId, imported.data.operationId);
console.log(operation.data.clientAction, operation.data.nextStep);

for await (const member of client.lists.members.listAll(listId)) console.log(member);
const csv = await client.lists.export(listId);

lists.listAll, lists.members.listAll and bulk.listAll read every page for you. They are free, so they need no maxResults.

Choose the right wait method

client.bulk.wait(jobId) returns when the job is completed, cancelled, failed or paused. Inspect the returned state before downloading results. client.lists.operations.wait(listId, operationId) returns when clientAction is done, resume or reconcile.

Neither method raises JobFailedError just because the operation stops unsuccessfully. Both can raise JobTimeoutError when the wait deadline passes.

List imports and Bulk jobs do not return the Job object used by live fetch and contact lookups. See client.lists, client.bulk and Timeouts and cancellation for the signatures and options.

Return to the TypeScript SDK overview.

FAQ

When should I use a List instead of Bulk enrichment?

A List keeps its members for ongoing work. Bulk enrichment processes up to 25,000 people and returns a results CSV.

Does bulk.wait throw when a Bulk job fails?

client.bulk.wait() returns the job when the status is completed, cancelled, failed or paused. Inspect job.data.status and job.data.links.results before downloading a CSV.

How do I resume a paused List import after restarting?

Pass your saved operationId to client.lists.importSignals() and follow the returned operation. Inspect clientAction and nextStep before deciding to resume.

How do I preserve accented names in a Bulk results CSV?

client.bulk.results() returns CSV text without the byte order mark. Prepend "\uFEFF" when saving the text for spreadsheet applications.