> ## Documentation Index
> Fetch the complete documentation index at: https://docs.datamagnet.co/llms.txt
> Use this file to discover all available pages before exploring further.

# Company Search DB

> Search Datamagnet's own database of company profiles by industry, location, headcount, type, founding year and LinkedIn identity — firmographic filters over previously collected records.

# Company Search DB

**Cost:** `10` credits/search.

Search Datamagnet's internal database of company profiles by firmographics. Like [People Search DB](/api-reference/endpoints/people-db-search), this queries records already collected rather than fetching live, so it returns instantly and doesn't consume collection capacity. Each page returns up to `500` companies.

## Company search DB endpoint

Every list field is OR'd within itself and AND'd across fields — `industries: ["Retail", "Restaurants"]` with `countries: ["US"]` means retail **or** restaurants, in the US.

**At least one filter is required.** A search with none is refused with a `422`, uncharged: there is no useful answer to "return anything" over 38 million companies.

<Warning>
  Most of these filters match the stored value **exactly**, not as a substring — that is what lets an index answer them on a table this size. Exact means exact: `"Software Development"` matches, `"software"` matches nothing. Where a field has more than one spelling in the data, pass every spelling you want, and see the coverage table at the end for how much of the database each field is filled on.
</Warning>

### Industry and type

<ParamField body="industries" type="string[]">
  Filter by industry, matched exactly against LinkedIn's own taxonomy string — `Medical Practices`, `Construction`, `Restaurants`, `Retail`, `Real Estate`, `Insurance`, `Software Development`.

  Two vintages of the taxonomy coexist in the data and nothing merges them: `Computer Software` is the legacy spelling of `Software Development`. Pass both when you want both.

  Example: `["Software Development", "Computer Software"]`
</ParamField>

<ParamField body="company_types" type="string[]">
  Filter by company type, matched exactly. Values seen in the data: `Privately Held`, `Public Company`, `Nonprofit`, `Self-Owned`, `Self-Employed`, `Partnership`, `Government Agency`, `Educational`.

  Example: `["Privately Held", "Public Company"]`
</ParamField>

<ParamField body="entity_types" type="string[]">
  What kind of LinkedIn page this is: `company`, `school` or `showcase`. Case-insensitive.

  Example: `["company"]`
</ParamField>

### Location

<ParamField body="countries" type="string[]">
  Filter by country as an ISO-3166-1 alpha-2 code, not a name — `US`, not `United States`. Case-insensitive.

  Example: `["US", "GB", "DE"]`
</ParamField>

<ParamField body="regions" type="string[]">
  State, province or other first-level region, matched exactly as stored. Example: `["California", "Texas"]`
</ParamField>

<ParamField body="cities" type="string[]">
  City, matched exactly as stored. Example: `["San Francisco", "Austin"]`
</ParamField>

### Size

<ParamField body="min_employees" type="integer">
  Minimum employee count. This is the numeric headcount, filled on about 42% of companies — for broader coverage use `size_bands`, which is filled on 98%.

  Example: `50`
</ParamField>

<ParamField body="max_employees" type="integer">
  Maximum employee count. Example: `500`
</ParamField>

<ParamField body="size_bands" type="string[]">
  Filter by LinkedIn's headcount band, matched exactly as stored: `1 employee`, `2-10 employees`, `11-50 employees`, `51-200 employees`, `201-500 employees`, `501-1,000 employees`, `1,001-5,000 employees`, `5,001-10,000 employees`, `10,001+ employees`.

  Older records carry shorter spellings of the same bands (`1-10`, `11-50`) and a few carry `0+ employees`. Pass every spelling you want matched — these are exact comparisons, not ranges.

  Example: `["11-50 employees", "51-200 employees"]`
</ParamField>

### Age and reach

<ParamField body="founded_min" type="integer">
  Founded in or after this year. Example: `2010`
</ParamField>

<ParamField body="founded_max" type="integer">
  Founded in or before this year.

  The founding year is stored as free text, so it is read as the first four digits of the value — `1998-2000 (relocated 2015)` reads as 1998, `2,024` reads as 2024. A company whose stored value holds no year at all never matches either bound.

  Example: `2020`
</ParamField>

<ParamField body="min_followers" type="integer">
  Minimum LinkedIn follower count. Example: `1000`
</ParamField>

### Web presence

<ParamField body="has_website" type="boolean">
  `true` returns only companies we hold a website for, `false` only those we hold none for. Like the contactability filters on the people search, this describes our records rather than the company.

  Example: `true`
</ParamField>

### LinkedIn identity

<ParamField body="linkedin_ids" type="string[]">
  Filter by numeric LinkedIn company ID. Exact match, and the fastest way to hydrate a list of companies you already know.

  Example: `["1035", "1441"]`
</ParamField>

<ParamField body="linkedin_usernames" type="string[]">
  Filter by LinkedIn universal name — the last path segment of the company URL. Case-insensitive, exact match.

  Example: `["stripe", "plaid"]`
</ParamField>

### Paging

<Note>
  Results are **not ordered**. Nothing worth sorting by is indexed on a table this size, so a sort would mean collecting every match before returning a page of them. Paging with `limit`/`offset` is therefore best-effort: it walks the result set, but the order it walks in is not guaranteed to be stable between calls.
</Note>

<ParamField body="limit" default={50} type="integer">
  Maximum number of companies to return per page, from `1` to `500`. A value outside that range is rejected rather than quietly reduced.
</ParamField>

<ParamField body="offset" default={0} type="integer">
  Number of results to skip, for pagination.
</ParamField>

### Unrecognised fields

A field name this endpoint doesn't know is not applied. The search still runs, and the response carries an `ignored_filters` array naming what was dropped — so a mistyped `industry` (for `industries`) shows up as a named mistake instead of a page of results that looks filtered but isn't.

If **every** filter in the request was unrecognised, the search is refused with a `422` and no credits are charged.

***

## Response

<RequestExample>
  ```json Request theme={null}
  {
    "industries": ["Software Development", "Computer Software"],
    "countries": ["US"],
    "regions": ["California"],
    "size_bands": ["51-200 employees", "201-500 employees"],
    "company_types": ["Privately Held"],
    "founded_min": 2010,
    "min_followers": 1000,
    "has_website": true,
    "limit": 50,
    "offset": 0
  }
  ```
</RequestExample>

<ResponseExample>
  ```json Response theme={null}
  {
    "message": [
      {
        "id": 84210,
        "linkedin_id": "1035",
        "username": "examplesoft",
        "linkedin_url": "https://www.linkedin.com/company/examplesoft",
        "entity_type": "company",
        "name": "ExampleSoft",
        "industry": "Software Development",
        "headcount_range": "51-200 employees",
        "employee_count": 138,
        "company_type": "Privately Held",
        "founded": "2013",
        "followers": 8421,
        "domain": "https://examplesoft.com",
        "headquarters": "San Francisco, California, United States",
        "hq_city_state": "San Francisco, California",
        "country_code": "US",
        "region": "California",
        "city": "San Francisco",
        "updated_at": "2026-08-02T09:14:55"
      }
    ],
    "credit_used": 10,
    "total": 1
  }
  ```
</ResponseExample>

## The response model

Results never carry the company description, the long-form `info` block or the raw collected payload. Those three are the bulk of the stored record, and a search that returned them would spend its whole budget fetching them. Use [Company](/api-reference/endpoints/company) on a result's `linkedin_url` for the full profile.

<ResponseField name="message" type="array">
  List of matching companies.

  <Expandable title="Company object">
    <ResponseField name="id" type="integer">
      Internal Datamagnet company ID.
    </ResponseField>

    <ResponseField name="linkedin_id" type="string">
      Numeric LinkedIn company ID.
    </ResponseField>

    <ResponseField name="username" type="string">
      LinkedIn universal name (the last segment of the company URL).
    </ResponseField>

    <ResponseField name="linkedin_url" type="string">
      LinkedIn company page URL.
    </ResponseField>

    <ResponseField name="entity_type" type="string">
      `company`, `school` or `showcase`.
    </ResponseField>

    <ResponseField name="name" type="string">
      Company name.
    </ResponseField>

    <ResponseField name="industry" type="string">
      LinkedIn industry taxonomy string.
    </ResponseField>

    <ResponseField name="headcount_range" type="string">
      LinkedIn headcount band, e.g. `51-200 employees`.
    </ResponseField>

    <ResponseField name="employee_count" type="integer">
      Numeric employee count, when available.
    </ResponseField>

    <ResponseField name="company_type" type="string">
      e.g. `Privately Held`, `Public Company`, `Nonprofit`.
    </ResponseField>

    <ResponseField name="founded" type="string">
      Founding year as stored. Free text: usually a year, occasionally a range.
    </ResponseField>

    <ResponseField name="followers" type="integer">
      LinkedIn follower count.
    </ResponseField>

    <ResponseField name="domain" type="string">
      Company website.
    </ResponseField>

    <ResponseField name="headquarters" type="string">
      Full headquarters location string.
    </ResponseField>

    <ResponseField name="hq_city_state" type="string">
      Headquarters city and region.
    </ResponseField>

    <ResponseField name="country_code" type="string">
      ISO-3166-1 alpha-2 country code.
    </ResponseField>

    <ResponseField name="region" type="string">
      State, province or first-level region.
    </ResponseField>

    <ResponseField name="city" type="string">
      City.
    </ResponseField>

    <ResponseField name="updated_at" type="string">
      When this record was last refreshed. Every figure above is as old as this timestamp — read it beside `employee_count` and `followers` in particular.
    </ResponseField>
  </Expandable>
</ResponseField>

<ResponseField name="credit_used" type="integer">
  Number of credits used for this request. Example: `10`
</ResponseField>

<ResponseField name="total" type="integer">
  Number of results returned in this response.
</ResponseField>

<ResponseField name="ignored_filters" type="string[]">
  Present only when the request contained field names this endpoint doesn't recognise. Names them, so a typo shows up as a typo rather than as results that look filtered but aren't.
</ResponseField>

## Field coverage

A filter can only return companies whose record holds that field, so coverage is the real ceiling on any search. Measured across 38.4M companies on 2026-09-22:

| Filter                            | Field is filled on |
| --------------------------------- | ------------------ |
| `size_bands`                      | 97.8%              |
| `countries`                       | 87.8%              |
| `industries`                      | 85.3%              |
| `regions`                         | 77.3%              |
| `cities`                          | 73.1%              |
| `has_website`                     | 72.0%              |
| `min_followers`                   | 64.2%              |
| `company_types`                   | 43.3%              |
| `min_employees` / `max_employees` | 41.8%              |
| `founded_min` / `founded_max`     | 37.4%              |

Combining a well-covered filter with a sparse one narrows twice: `min_employees` with `founded_min` can only return the companies that carry both.

## Errors

| Status | Meaning                                                                                                                        | What to do                                                             |
| ------ | ------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------------------- |
| `400`  | The body was not a JSON object, or `limit` was outside `1`–`500`, or `offset` was negative. `message` names the problem.       | Fix the request.                                                       |
| `422`  | The request carried no filters at all, or every filter in it was an unrecognised field name. `message` lists what is accepted. | Add a filter, or correct the name.                                     |
| `504`  | The search ran too long to answer.                                                                                             | Narrow it and retry — a country or a size band alongside the industry. |

Nothing is charged on any error.
