---
title: "Search companies with indexed fields only"
method: POST
path: "/company/search"
tags: ["Company APIs", "Search APIs"]
---

# Search companies with indexed fields only

`POST /company/search`

Search the Crustdata company database using filter conditions. Supports complex
AND/OR filter logic, cursor-based pagination, sorting, and field selection.
Only indexed fields are searchable; use /company/enrich for non-indexed fields
like news, people, or web_traffic.
<Note>
    Default `rate-limit` is 30 requests per minute. Send an email to [gtm@crustdata.co](mailto:gtm@crustdata.co) to discuss higher limits if needed for your use case.
</Note>

## Headers

- `x-api-version` '2025-11-01', required

## Request body

- CompanySearchRequest — Request body for searching the company database using indexed fields.
  - `filters` union — Search filters. Use a single `SearchCondition` or an and/or `SearchConditionGroup`.
    - SearchCondition — A single filter condition used to narrow job search results.
      - `field` string, required — Field name to filter on. Use the exact dot-path below. Only indexed fields are filterable. Job details: `job_details.title`, `job_details.category`, `job_details.workplace_type`, `job_details.reposted_job`, `job_details.url` Company basic info: `company.basic_info.company_id`, `company.basic_info.name`, `company.basic_info.primary_domain`, `company.basic_info.professional_network_id`, `company.basic_info.industries` Company firmographics: `company.headcount.total`, `company.headcount.range`, `company.followers.count`, `company.revenue.estimated.lower_bound_usd` Location: `location.raw`, `location.country`, `location.state`, `location.district`, `location.city`. For radius filtering with `geo_distance`/`geo_exclude`, use `location` (or `location.raw` — both target the same geo point). Content: `content.description` Identifiers: `crustdata_job_id` Metadata: `metadata.date_added`, `metadata.date_updated`
      - `type` '=' | '!=' | '<' | '=<' | '>' | '=>' | 'in' | 'not_in' | '(.)' | '[.]' | 'geo_distance' | 'geo_exclude', required — Filter operator. - `=`, `!=`: exact match or negation - `<`, `=<`, `>`, `=>`: numeric or date comparison - `in`, `not_in`: set membership (value must be an array) - `(.)`: case-insensitive substring match (useful for keywords in title or description) - `[.]`: case-insensitive exact word/phrase match - `geo_distance`: match jobs within a radius of a point (value must be a geo object; only on `location` and `location.raw`) - `geo_exclude`: exclude jobs within a radius of a point (value must be a geo object; only on `location` and `location.raw`)
      - `value` union, required — Filter value. Type depends on `type`: a scalar for comparison operators, an array for `in`/`not_in`, or a geo object for `geo_distance`/`geo_exclude`.
        - string
        - number
        - integer
        - boolean
        - union[]
          - union
            - string
            - number
            - integer
        - object — Geo radius value for `geo_distance`/`geo_exclude`. Provide a center point as either a `location` string (geocoded server-side) or an explicit `lat_lng` pair, plus a `distance` radius. If both `location` and `lat_lng` are supplied, `lat_lng` is used and geocoding is skipped.
          - `location` string — Free-form place name to geocode into the center point (e.g. a city). Required unless `lat_lng` is provided.
          - `lat_lng` number[] — Explicit center point as a `[latitude, longitude]` pair of numbers (latitude -90 to 90, longitude -180 to 180). Takes precedence over `location`.
          - `distance` number, required — Radius around the center point. Must be a positive number, in the unit given by `unit`.
          - `unit` 'km' | 'mi' | 'miles' | 'm' | 'meters' | 'ft' | 'feet' — Distance unit for `distance`. Defaults to `km`.
    - SearchConditionGroup — A group of filter conditions combined with AND or OR logic. Supports nesting for complex queries.
      - `op` 'and' | 'or', required — Logical operator to combine the child conditions.
      - `conditions` union[], required — Array of conditions or nested condition groups.
        - union
          - SearchCondition — A single filter condition used to narrow job search results.
            - `field` string, required — Field name to filter on. Use the exact dot-path below. Only indexed fields are filterable. Job details: `job_details.title`, `job_details.category`, `job_details.workplace_type`, `job_details.reposted_job`, `job_details.url` Company basic info: `company.basic_info.company_id`, `company.basic_info.name`, `company.basic_info.primary_domain`, `company.basic_info.professional_network_id`, `company.basic_info.industries` Company firmographics: `company.headcount.total`, `company.headcount.range`, `company.followers.count`, `company.revenue.estimated.lower_bound_usd` Location: `location.raw`, `location.country`, `location.state`, `location.district`, `location.city`. For radius filtering with `geo_distance`/`geo_exclude`, use `location` (or `location.raw` — both target the same geo point). Content: `content.description` Identifiers: `crustdata_job_id` Metadata: `metadata.date_added`, `metadata.date_updated`
            - `type` '=' | '!=' | '<' | '=<' | '>' | '=>' | 'in' | 'not_in' | '(.)' | '[.]' | 'geo_distance' | 'geo_exclude', required — Filter operator. - `=`, `!=`: exact match or negation - `<`, `=<`, `>`, `=>`: numeric or date comparison - `in`, `not_in`: set membership (value must be an array) - `(.)`: case-insensitive substring match (useful for keywords in title or description) - `[.]`: case-insensitive exact word/phrase match - `geo_distance`: match jobs within a radius of a point (value must be a geo object; only on `location` and `location.raw`) - `geo_exclude`: exclude jobs within a radius of a point (value must be a geo object; only on `location` and `location.raw`)
            - `value` union, required — Filter value. Type depends on `type`: a scalar for comparison operators, an array for `in`/`not_in`, or a geo object for `geo_distance`/`geo_exclude`.
              - …
          - object — Nested filter group (recursive AND/OR of conditions or further groups).
            - `op` 'and' | 'or', required — Logical operator to combine the child conditions.
            - `conditions` object[], required — Array of conditions or further nested groups.
              - …
  - `cursor` string — Pagination cursor from a previous response's `next_cursor`. Omit on the first page.
  - `limit` integer
  - `sorts` SearchSort[] — Sort directives applied to matched companies in order.
    - `field` string, required — Field name to sort on. Supports the same dot-path names used for filters, e.g., `metadata.date_added`, `metadata.date_updated`, `company.headcount.total`, `company.followers.count`.
    - `order` 'asc' | 'desc', required — Sort direction.
  - `fields` string[] — Fields to return in the response. Use dot-notation for nested fields (e.g., "basic_info.name", "headcount.total"). Only requested fields appear in the response. Valid top-level groups for search: basic_info, revenue, headcount, funding, hiring, locations, taxonomy, followers, social_profiles, software_reviews, metadata, updated_at, indexed_at, crustdata_company_id. Some groups are filter-only and cannot be selected here (for example roles, skills, seo, competitors), and groups not in the search index (for example news, people, web_traffic, employee_reviews) are rejected — use /company/enrich for those.

## Response `200`

Companies matching the search criteria

- CompanySearchResponse — Paginated response from the /company/search endpoint.
  - `companies` CompanySearch[], required
    - `crustdata_company_id` integer
    - `updated_at` string, date-time, nullable
    - `indexed_at` string, date-time, nullable
    - `metadata` object
      - `growth_calculation_date` string, nullable
    - `basic_info` object
      - `crustdata_company_id` integer, nullable
      - `name` string, nullable
      - `primary_domain` string, nullable
      - `all_domains` string[], nullable
      - `website` string, nullable
      - `professional_network_url` string, nullable
      - `professional_network_id` string, nullable
      - `profile_name` string, nullable
      - `logo_permalink` string, nullable
      - `description` string, nullable
      - `company_type` string, nullable
      - `year_founded` integer, nullable
      - `employee_count_range` string, nullable
      - `markets` string[], nullable
      - `industries` string[], nullable
    - `revenue` object
      - `estimated` object
        - `lower_bound_usd` integer, nullable
        - `upper_bound_usd` integer, nullable
      - `public_markets` object
        - `ipo_date` string, date, nullable
        - `stock_symbols` string[], nullable
        - `fiscal_year_end` string, nullable
      - `acquisition_status` string, nullable
    - `headcount` object — Employee footprint
      - `total` integer, nullable
      - `largest_headcount_country` string, nullable
      - `growth_percent` object — Headcount growth percent by period. Keys are period suffixes (`1m`, `3m`, `6m`, `12m`); values are percentage changes over the trailing window. Each period is also filterable via `headcount.growth_percent.{period}` on `/company/search`.
      - `growth_absolute` object — Headcount absolute change by period. Keys are period suffixes (`1m`, `3m`, `6m`, `12m`); values are absolute employee-count deltas over the trailing window. Each period is also filterable via `headcount.growth_absolute.{period}` on `/company/search`.
    - `software_reviews` object
      - `review_count` integer, nullable
      - `average_rating` number, nullable
      - `review_count_mom_pct` number, nullable
      - `review_count_qoq_pct` number, nullable
      - `review_count_yoy_pct` number, nullable
    - `funding` object
      - `total_investment_usd` number, nullable
      - `last_round_amount_usd` number, nullable
      - `last_fundraise_date` string, date, nullable
      - `last_round_type` string, nullable
      - `investors` string[], nullable
    - `hiring` object
      - `openings_count` integer
      - `openings_growth_percent` object
      - `by_function_qoq_pct` object
      - `by_function_6m_pct` object
    - `locations` object
      - `country` string, nullable
      - `headquarters` string, nullable
      - `street_address` string, nullable — HQ street address (e.g. "510 Townsend St.")
      - `state` string, nullable
      - `all_office_addresses` string[], nullable
    - `social_profiles` object
      - `crunchbase` object
        - `url` string, nullable
        - `uuid` string, nullable
      - `twitter_url` string, nullable
      - `professional_network` string, nullable — Profile URL for the company. Same value also surfaced at basic_info.professional_network_url.
    - `taxonomy` object
      - `professional_network_specialities` string[], nullable
      - `professional_network_industry` string, nullable
      - `categories` string[], nullable
    - `followers` object
      - `count` integer, nullable
      - `mom_percent` number, nullable
      - `qoq_percent` number, nullable
      - `six_months_growth_percent` number, nullable
      - `yoy_percent` number, nullable
  - `next_cursor` string, nullable
  - `total_count` integer, nullable
  - `query` object

## Other responses

- `400` — Invalid search request
- `401` — Unauthorized - invalid or missing API key
- `403` — Forbidden - search access not available
- `500` — Internal server error

---

[API](https://skmtc.dev/crustdata/apis/batch-api.md) · [All operations](https://skmtc.dev/crustdata/apis/batch-api/llms.txt) · [OpenAPI document](https://skmtc-service-production.skmtc.workers.dev/v1/apis/crustdata/batch-api/revisions/581689e66ae7/schema)
