Skip to content

Migrations & changes

Migrating company search to organizations

New

Move company search calls from /v2/search/companies to /v2/search/organizations.

Last verified

Company search has a new home: POST /v2/search/organizations. It returns full organization profiles instead of search hits, paginates with cursors instead of page numbers, accepts three new filters, and ships with a free count endpoint.

The previous endpoint, POST /v2/search/companies, is deprecated since October 16, 2026. It keeps working for now and no retirement date is announced yet, but it is no longer documented in the endpoint catalog. Once it is retired, calls to /v2/search/companies and /v2/search/companies/available-fields will return 410 Gone with the error code ENDPOINT_GONE, error.details.alternative naming the endpoint to call instead and error.details.docs linking this guide. This guide covers everything that changes when you move to /v2/search/organizations.

What changes

AreaPOST /v2/search/companiesPOST /v2/search/organizations
Path/v2/search/companies/v2/search/organizations
ResultsSearch hits (name, size, industry, city and country)Full organization profiles, the same shape as the Company profile endpoint
Paginationpage and perPage (default 100)cursor and perPage (default 25)
MetadatacurrentPage, pageNumber, perPage, totalperPage, count, nextCursor
Total matchesdata.metadata.total on every responseFree count endpoint
Pricing1 credit per page1 credit per organization delivered
FilterscompanyName, companyDomain, industry, employeeCountRange, location, maxDataAgeDateThe same, plus specialities, foundedYear and followersCount
Available fieldsGET /v2/search/companies/available-fieldsGET /v2/search/organizations/available-fields

Paths

BeforeAfter
POST /v2/search/companiesPOST /v2/search/organizations
GET /v2/search/companies/available-fieldsGET /v2/search/organizations/available-fields
(no equivalent)POST /v2/search/organizations/count

The method and the Authorization: Bearer YOUR_API_KEY header stay the same. Only the path changes.

Results are full profiles

The previous endpoint returned a light search hit, and the documented flow was to chain into the Company profile endpoint for the full data of a hit. Organization search returns complete profiles directly, so the second call is no longer needed.

Before, a hit looked like this:

JSON
{
  "id": "com_01jbd5vewyenebxgaz869ffe5t",
  "name": "Acme Corp",
  "publicId": "acme",
  "linkedinId": "12345678",
  "linkedinUrl": "https://www.social.com/company/acme",
  "employeesCount": 452,
  "followersCount": 28512,
  "employeeCountRange": { "start": 201, "end": 500 },
  "websiteUrl": "https://www.acmecorp.com",
  "tagline": "Building the future of work",
  "industry": "Software Development",
  "companyUpdateDate": "2026-03-18T09:12:44.000Z",
  "location": { "city": "San Francisco", "country": "US" }
}

After, each item of data.data is a full organization profile. Most fields keep their name (id, publicId, linkedinId, linkedinUrl, employeesCount, followersCount, employeeCountRange, websiteUrl, tagline, industry), three change, and the profile adds description, phone, specialities, logoUrl, backgroundUrl, foundedOn and locations:

Search hitFull profile
namecompanyName
location.city, location.countryheadquarter.city, headquarter.country (still an ISO code), next to the street, postal code and region of the headquarters
companyUpdateDateNot part of the full profile. Filter on freshness with maxDataAgeDate, or read lastUpdate from the free Company profile status endpoint

If you chained Company profile calls after a search, drop them: the data is already in the search response.

Pagination moves from pages to cursors

The previous endpoint used page (1 to 50) and perPage (1 to 100, default 100), and reported currentPage, pageNumber and total in data.metadata. Organization search uses cursor pagination:

  • perPage stays, with a new default of 25 (still 1 to 100).
  • page is gone, and sending it returns 422 with UNKNOWN_FIELD. Send the nextCursor value from the previous response as cursor to get the next page, with the same filters.
  • nextCursor is null on the last page.
  • The cursor is opaque: send it back unchanged, without parsing or altering it.
  • The 50-page limit is gone: a cursor reaches every matching organization.

Before:

JavaScript
const response = await fetch("https://api.reversecontact.com/v2/search/companies", {
  method: "POST",
  headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
  body: JSON.stringify({ industry: "Software Development", page: 2, perPage: 100 })
});

const payload = await response.json();
const hits = payload.data.data;
console.log(`Page ${payload.data.metadata.currentPage} of ${payload.data.metadata.pageNumber}, ${payload.data.metadata.total} total`);

After:

JavaScript
const searchPage = async (cursor) => {
  const response = await fetch("https://api.reversecontact.com/v2/search/organizations", {
    method: "POST",
    headers: { "Authorization": "Bearer YOUR_API_KEY", "Content-Type": "application/json" },
    body: JSON.stringify({ industry: "Software Development", perPage: 25, cursor })
  });

  return response.json();
};

const page = await searchPage();
console.log(`${page.data.metadata.count} organizations in this page`);
if (page.data.metadata.nextCursor) {
  const nextPage = await searchPage(page.data.metadata.nextCursor);
}

Totals move to the count endpoint

The previous data.metadata.total field is gone: data.metadata.count is the number of organizations in the current page, not the size of the whole matching set. To size a query, call the free Organization search count endpoint with the same filters:

Shell
curl -X POST https://api.reversecontact.com/v2/search/organizations/count \
  -H "Authorization: Bearer YOUR_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{ "industry": "Software Development" }'

The response is data.count, the total number of matching organizations across all pages, and it costs 0 credits.

Pricing changes

The previous endpoint charged 1 credit per page, whatever the page contained. Organization search charges 1 credit per organization delivered: a page that returns 25 organizations costs 25 credits, and a page that returns no organization costs 0 credits. Rejected filters still cost 0 credits.

Three consequences for your migration:

  • perPage is now a credit control. Lower it to cap what a single request can spend.
  • A request needs as many credits available as its perPage before it runs, otherwise it returns 402 with INSUFFICIENT_CREDITS. Only the organizations delivered are then charged.
  • Size queries first with the free count endpoint instead of reading metadata.total from a billed page.

Filter changes

Existing filters keep their names and their values: companyName, companyDomain, industry (from the same industry list), employeeCountRange (the same headcount brackets), location (country, countryCode, region and city, matched on the headquarters) and maxDataAgeDate. Organization search also accepts filters the previous endpoint did not have:

FilterWhat it does
specialitiesMatch the specialities listed on the organization profile, one value or a list (OR-matched)
foundedYearKeep organizations founded within a year range, from 0 to 2100
followersCountKeep organizations within a follower count range

Two rules are stricter. A request needs at least one filter, and maxDataAgeDate cannot be that only filter: both return 422 with NO_FILTER_PROVIDED. Validation is otherwise unchanged in spirit: unknown fields, blank values and values outside a closed list return 422 with suggestions and cost 0 credits. Every filter is documented on the Organization search page.

Available fields moves too

If you discover filters dynamically, switch GET /v2/search/companies/available-fields to GET /v2/search/organizations/available-fields. The response keeps its shape, with two differences: data.entity is "organization", and data.fields lists cursor instead of page, next to every accepted filter and the allowedValues of closed vocabularies such as industries.

Migration checklist

  1. Replace the search path with POST /v2/search/organizations and the available-fields path with GET /v2/search/organizations/available-fields.
  2. Replace page with cursor handling: loop while data.metadata.nextCursor is not null.
  3. Review your perPage: the default is now 25, each delivered organization costs 1 credit, and the balance must cover perPage before the call.
  4. Replace data.metadata.total reads with a call to POST /v2/search/organizations/count.
  5. Map the renamed fields: name becomes companyName, location becomes headquarter, and companyUpdateDate is gone.
  6. Drop the Company profile calls you used to chain after a search: results are already full profiles.
  7. Make sure every request carries at least one filter other than maxDataAgeDate.

FAQ

Does /v2/search/companies still work?

Yes, for now. POST /v2/search/companies is deprecated since October 16, 2026, has left the documentation and has no retirement date yet. Once it is retired, it will return 410 Gone with the error code ENDPOINT_GONE and name POST /v2/search/organizations in error.details.alternative, so move to POST /v2/search/organizations now.

How do I get the total number of matching organizations with /v2/search/organizations?

POST /v2/search/organizations does not return a total: data.metadata.count is only the number of organizations in the current page. Call POST /v2/search/organizations/count with the same filters to get data.count, the total number of matching organizations across all pages, for 0 credits. See Organization search count.

How many credits does an organization search cost?

POST /v2/search/organizations charges 1 credit per organization delivered: a page that returns 25 organizations costs 25 credits, and a page that returns no organization costs 0 credits. Rejected filters also cost 0 credits, and lowering perPage caps what a single request can spend.

Which result fields change name in /v2/search/organizations?

In POST /v2/search/organizations results, name becomes companyName and location becomes headquarter, whose country is still an ISO code. companyUpdateDate is not part of the full profile: filter with maxDataAgeDate, or read lastUpdate from the free Company profile status endpoint.

No. Each item of data.data in a POST /v2/search/organizations response is already a full organization profile, with description, specialities, headquarter, locations, foundedOn and the other Company profile fields, so the Company profile calls you chained after a search can be dropped. See Company profile.