> Reverse Contact API documentation. This is the Markdown copy of https://docs.reversecontact.com/use-cases/build-a-list-of-companies
> Every page is listed at https://docs.reversecontact.com/llms.txt, every endpoint with its credit cost and status at https://docs.reversecontact.com/catalog.json

# Build a list of companies

> Build a company list with the search API. Count matches for free, filter by industry, headcount and location, use prompts, and cap credit spending.

- Last verified: 2026-11-04

Find companies by industry, headcount and headquarters location, or describe the companies you want in a sentence. You can count a filtered search for free before retrieving profiles. Search returns full company profiles synchronously from the index, within your credit budget.

## Which endpoint

| Input you have | Endpoint | Cost | Mode |
| --- | --- | --- | --- |
| Filters to count matches before buying profiles | [Company search count](https://docs.reversecontact.com/endpoints/search-companies-count) | Free | Synchronous |
| Explicit company filters | [Company search](https://docs.reversecontact.com/endpoints/search-companies) | 1 credit per company delivered. An empty page is free | Synchronous |
| A description of the companies to find | [Agentic Company Search](https://docs.reversecontact.com/endpoints/search-companies-prompt) | 1 credit per page plus 1 per company delivered | Synchronous |

The API routes use `/v2/search/organizations`. The reference pages linked above keep their existing company-search addresses.

## How it works

Set `RC_API_KEY` to your [API key](https://docs.reversecontact.com/authentication). Install the [TypeScript SDK](https://docs.reversecontact.com/sdk/javascript), [Python SDK](https://docs.reversecontact.com/sdk/python) or [CLI](https://docs.reversecontact.com/guides/cli) for your chosen example. Shell examples use `jq`. Prompt search is an alternative to filtered search, with its own charges.

### Count the companies that match

Count software companies headquartered in France, in the 51 to 200 employee bracket, founded in 2015 or later. Read `data.count` and reuse the same filters for the paid search. Leave `cursor` and `perPage` out of the count request.

**Code Examples**

```bash [cURL]
curl --fail-with-body -sS -X POST https://api.reversecontact.com/v2/search/organizations/count \
  -H "Authorization: Bearer $RC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"industry": "Software Development", "employeeCountRange": {"min": 51, "max": 200}, "foundedYear": {"min": 2015}, "location": {"countryCode": "FR"}}'
```
```typescript [TypeScript SDK]
import ReverseContact from "@reverse-contact/sdk";

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

const count = await client.search.countOrganizations({
  industry: "Software Development",
  employeeCountRange: { min: 51, max: 200 },
  foundedYear: { min: 2015 },
  location: { countryCode: "FR" }
});
console.log("Matching companies:", count.data.count);
```
```python [Python SDK]
import os

from reversecontact import ReverseContact

with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
    count = client.search.count_organizations(
        industry="Software Development",
        employee_count_range={"min": 51, "max": 200},
        founded_year={"min": 2015},
        location={"countryCode": "FR"},
    )
    print("Matching companies:", count.data.count if count.data else None)
```

### Retrieve the company profiles within budget

Retrieve at most 100 companies for at most 100 credits. Request pages of up to 25 companies, with a smaller final request when needed. The raw API returns companies in `data.data` and the cursor in `data.metadata.nextCursor`. The SDKs handle pagination, and the CLI counts for free before searching.

**Code Examples**

```bash [cURL]
remaining=100
cursor=""
filters='{"industry": "Software Development", "employeeCountRange": {"min": 51, "max": 200}, "foundedYear": {"min": 2015}, "location": {"countryCode": "FR"}}'
while [ "$remaining" -gt 0 ]; do
  size=$((remaining < 25 ? remaining : 25))
  body=$(printf '%s' "$filters" | jq --arg cursor "$cursor" --argjson size "$size" \
    '. + {perPage: $size} + (if $cursor == "" then {} else {cursor: $cursor} end)')
  result=$(curl --fail-with-body -sS -X POST https://api.reversecontact.com/v2/search/organizations \
    -H "Authorization: Bearer $RC_API_KEY" \
    -H "Content-Type: application/json" -d "$body") || break
  printf '%s' "$result" | jq -c '.data.data[]'
  delivered=$(printf '%s' "$result" | jq -er '.data.data | length')
  remaining=$((remaining - delivered))
  next_cursor=$(printf '%s' "$result" | jq -r '.data.metadata.nextCursor // empty')
  [ -z "$next_cursor" ] && break
  [ "$next_cursor" = "$cursor" ] && { echo "Repeated cursor" >&2; break; }
  cursor=$next_cursor
done
```
```typescript [TypeScript SDK]
import ReverseContact from "@reverse-contact/sdk";

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

for await (const company of client.search.iterOrganizations(
  {
    industry: "Software Development",
    employeeCountRange: { min: 51, max: 200 },
    foundedYear: { min: 2015 },
    location: { countryCode: "FR" },
    perPage: 25
  },
  { maxResults: 100 }
)) {
  console.log(company.companyName, company.websiteUrl);
}
```
```python [Python SDK]
import os

from reversecontact import ReverseContact

with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
    for company in client.search.iter_organizations(
        industry="Software Development",
        employee_count_range={"min": 51, "max": 200},
        founded_year={"min": 2015},
        location={"countryCode": "FR"},
        per_page=25,
        max_results=100,
    ):
        if company is not None:
            print(company.company_name, company.website_url)
```
```bash [CLI]
remaining=100
cursor=""
while [ "$remaining" -gt 0 ]; do
  size=$((remaining < 25 ? remaining : 25))
  if [ -n "$cursor" ]; then
    result=$(rc search organizations --industry "Software Development" --size 51-200 --founded-year 2015- --country-code FR --limit "$size" --cursor "$cursor" --json) || break
  else
    result=$(rc search organizations --industry "Software Development" --size 51-200 --founded-year 2015- --country-code FR --limit "$size" --json) || break
  fi
  printf '%s' "$result" | jq -c '.data.data[]'
  delivered=$(printf '%s' "$result" | jq -er '.data.data | length')
  remaining=$((remaining - delivered))
  next_cursor=$(printf '%s' "$result" | jq -r '.data.metadata.nextCursor // empty')
  [ -z "$next_cursor" ] && break
  [ "$next_cursor" = "$cursor" ] && { echo "Repeated cursor" >&2; break; }
  cursor=$next_cursor
done
```

### Search from a description

You can use Agentic Company Search with a `prompt`. Inspect `data.interpretation.filters` and `warnings` before continuing. This example requests one page of up to 25 companies for at most 26 credits. Describe every criterion in the prompt instead of adding explicit filter fields.

**Code Examples**

```bash [cURL]
curl --fail-with-body -sS -X POST https://api.reversecontact.com/v2/search/organizations/prompt \
  -H "Authorization: Bearer $RC_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"prompt": "Software companies headquartered in France with 51 to 200 employees, founded since 2015", "perPage": 25}'
```
```typescript [TypeScript SDK]
import ReverseContact from "@reverse-contact/sdk";

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

const page = await client.search.organizationsByPrompt({
  prompt: "Software companies headquartered in France with 51 to 200 employees, founded since 2015",
  perPage: 25
});
console.log("Filters:", page.interpretation?.filters);
console.log("Warnings:", page.interpretation?.warnings);
console.log(page.data, "credits:", page.quotas?.creditsConsumed);
```
```python [Python SDK]
import os

from reversecontact import ReverseContact

with ReverseContact(api_key=os.environ["RC_API_KEY"]) as client:
    page = client.search.organizations_by_prompt(
        prompt="Software companies headquartered in France with 51 to 200 employees, founded since 2015",
        per_page=25,
    )
    if page.interpretation is not None:
        print("Filters:", page.interpretation.filters)
        print("Warnings:", page.interpretation.warnings)
    print(page.data, "next cursor:", page.next_cursor)
```

## What it costs

Company search costs **1 credit per company delivered**. An empty page costs nothing, and Company search count is free. The full company profile is included, so you do not need a second fetch to retrieve its fields.

Agentic Company Search costs **1 credit per page for the search, plus 1 credit per company delivered**. The 1-credit page fee also applies to empty pages. Before a request runs, your available balance must cover `perPage` credits for filtered search, or `perPage + 1` for a prompt search. Otherwise, the API returns `402 INSUFFICIENT_CREDITS` without charging.

> [!NOTE]
> Count a query for free, then retrieve 100 companies over four full pages of 25: filtered search costs **100 credits**. The same four full pages through Agentic Company Search cost 100 + 4 = **104 credits**. An additional empty prompt page adds **1 credit**.

SDK iterators use `maxResults` / `max_results` to cap profiles, but this limit does not cover the extra page fees of Agentic Company Search. Limit prompt requests page by page, or configure an [API key credit limit](https://docs.reversecontact.com/guides/api-key-management) to cap total spending.

## Good to know

Company search and Company search count require at least one filter. The `maxDataAgeDate` filter cannot be used alone. Filters combine with AND.

Use `industry` values such as `Software Development` from [Industry values](https://docs.reversecontact.com/reference/industries), and full `location.area` ids such as `MC:DACH` from [Area values](https://docs.reversecontact.com/reference/areas). Put country codes in `location.countryCode` (`FR`) and country names in `location.country` (`France`).

The `employeeCountRange` filter matches whole size brackets. For example, `{ "min": 51, "max": 200 }` matches the 51 to 200 bracket. A range that contains no complete bracket returns no companies. Unknown fields and invalid closed-list values return `422` and cost 0 credits. The [Company search request reference](https://docs.reversecontact.com/endpoints/search-companies#request-body) lists the filters and their accepted values.

Request 1 to 100 companies per page, 25 by default. Keep filters unchanged and pass `data.metadata.nextCursor` back as `cursor`. Stop only when the cursor is `null` or your budget is spent. A short or empty page can still have a next cursor, and there is no `page` parameter.

For prompt search, resend the same prompt. After the first paid prompt page, send `data.interpretation.filters` to Company search count to get a free total.

Search uses cached profiles. See [Keep profiles fresh](https://docs.reversecontact.com/use-cases/keep-profiles-fresh) when you need current company data, and check the [rate limits](https://docs.reversecontact.com/guides/rate-limits) when paging at scale. Search count calls still count toward those request limits.

The examples print profiles for your application to store. To save companies in a persistent Reverse Contact List, use [Lists: orchestrate enrichment](https://docs.reversecontact.com/guides/lists).

## FAQ

### How do I build a company list by industry and employee count?

Send `industry` and `employeeCountRange` to Company search count to count matches for free. Use the same filters with `POST /v2/search/organizations` to retrieve full company profiles at 1 credit per company delivered.

### Why does company search return no results for my employee range?

The `employeeCountRange` filter must contain whole size brackets. A range such as 51 to 200 matches that bracket. A range that contains no complete bracket returns no companies.

### How do I cap company search credits?

For filtered Company search, use an SDK iterator with `maxResults` / `max_results` or request no more companies than the remaining budget. Agentic Company Search adds 1 credit per page, so budget those fees separately or use an API key credit limit.

### Can I search for companies with a plain-language prompt?

Yes. Agentic Company Search accepts a `prompt` and returns the interpreted filters and warnings. Each page costs 1 credit plus 1 per company delivered. You cannot add explicit filter fields alongside the prompt.

### How do I get the next page of company search results?

Send `data.metadata.nextCursor` as `cursor`. Keep the same filters for Company search, or the same prompt for Agentic Company Search. Continue until the cursor is `null` or your budget is spent. An empty page alone does not mean the search has ended.
