Skip to main content
Use this when you want to explore a market, build a target account list, or segment companies by criteria like geography, industry, funding, or headcount. The Company Search API lets you find companies by domain, country, industry, funding, headcount, and more. This page walks you through the API step by step, starting with the simplest possible request and building up to advanced queries. Every request goes to the same endpoint:
POST https://api.crustdata.com/company/search
Replace YOUR_API_KEY in each example with your actual API key. All requests require the x-api-version: 2025-11-01 header.

Request body

ParameterTypeRequiredDefaultDescription
filtersobjectNoA single filter condition or a nested and/or group. Omit to match all companies.
fieldsstring[]Noall fieldsDot-path fields to include in each company object. Always specify in production.
sortsobject[]NoSort rules. Each has column (field path) and order (asc or desc).
limitintegerNo20Companies per page. Max: 1000.
cursorstringNoPagination cursor from a previous response.

Response body

FieldTypeDescription
companiesarrayMatching company records with requested fields.
next_cursorstring or nullCursor for the next page. null when no more pages.
total_countinteger or nullTotal matching companies (may be null for broad queries).
queryobjectNormalized query representation used by the backend.

Rate limits and credits

Current platform behavior — not specified in the OpenAPI contract:
  • Rate limit: 60 requests per minute.
  • Credits: 1 credit per 100 companies returned.
  • No results, no charge: Credits are only deducted when data is returned.

Your first search: find a company by domain

The simplest search finds a company by its exact primary domain. You pass a single filter with the = operator.
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "field": "basic_info.primary_domain",
      "type": "=",
      "value": "retool.com"
    },
    "limit": 1,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "basic_info.primary_domain",
      "basic_info.year_founded",
      "headcount.total",
      "locations.hq_country",
      "funding.total_investment_usd"
    ]
  }'
Response trimmed for clarity. The query field contains the normalized query used by the backend — useful for debugging.

Understanding the response

Every search response has four fields:
  • companies — an array of matching company records. Each record contains the fields you requested in fields.
  • next_cursor — a pagination token. Pass it in the next request to get the next page. null means there are no more pages.
  • total_count — how many companies match your filters across the full database (may be null for very broad queries).
  • query — the normalized query representation used by the backend. Useful for debugging; you can generally ignore this in production.

How to interpret results

  • next_cursor is null: You have reached the last page. No more results.
  • total_count is null: The exact count is too expensive to compute for this query. Use next_cursor to determine if more pages exist.
  • Empty companies array: No companies matched your filters. Broaden your filters or check values with Autocomplete.

Controlling which fields come back

The fields parameter lets you pick exactly which fields to include. This keeps your responses small and focused. If you omit fields, the API returns all available fields for each company.

Combine filters with and

Real searches need more than one criterion. Wrap multiple conditions inside an op: "and" group to require all of them. This search finds software development companies headquartered in the USA, sorted by headcount (largest first).
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "op": "and",
      "conditions": [
        {
          "field": "taxonomy.linkedin_industry",
          "type": "=",
          "value": "Software Development"
        },
        {
          "field": "locations.hq_country",
          "type": "in",
          "value": ["USA"]
        }
      ]
    },
    "sorts": [{"column": "headcount.total", "order": "desc"}],
    "limit": 2,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "basic_info.primary_domain",
      "taxonomy.linkedin_industry",
      "headcount.total",
      "locations.hq_country"
    ]
  }'
Response trimmed for clarity.
The key difference from the first example: instead of a single filters object, you now have a group with op: "and" and a conditions array. Every condition must match for a company to be included.

Use or and nested logic

Use op: "or" when a company should match any condition. You can also nest and/or groups for complex queries. This search finds companies that are either in the “SaaS” Crunchbase category or have over $5M in total investment, AND are headquartered in the USA.
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "op": "and",
      "conditions": [
        {
          "op": "or",
          "conditions": [
            {
              "field": "taxonomy.crunchbase_categories",
              "type": "in",
              "value": ["SaaS"]
            },
            {
              "field": "funding.total_investment_usd",
              "type": ">",
              "value": 5000000
            }
          ]
        },
        {
          "field": "locations.hq_country",
          "type": "=",
          "value": "USA"
        }
      ]
    },
    "sorts": [{"column": "headcount.total", "order": "desc"}],
    "limit": 2,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "headcount.total",
      "taxonomy.crunchbase_categories",
      "funding.total_investment_usd"
    ]
  }'
The outer and requires both conditions: the inner or matches either SaaS companies or well-funded companies, and the outer condition restricts to US-headquartered companies.

Find well-funded companies in a country

This is a common pattern for sales and investor research: find companies in a specific market with significant funding. This search finds US-based companies with over $10M in total investment, sorted by funding (highest first).
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "op": "and",
      "conditions": [
        {
          "field": "locations.hq_country",
          "type": "in",
          "value": ["USA"]
        },
        {
          "field": "funding.total_investment_usd",
          "type": ">",
          "value": 10000000
        }
      ]
    },
    "sorts": [{"column": "funding.total_investment_usd", "order": "desc"}],
    "limit": 2,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "basic_info.primary_domain",
      "locations.hq_country",
      "funding.total_investment_usd",
      "headcount.total"
    ]
  }'
Response trimmed for clarity.

How sorts work

The sorts parameter orders your results. Each sort rule needs:
  • column — a dot-path field (e.g., funding.total_investment_usd, headcount.total, basic_info.name).
  • order — either asc (ascending) or desc (descending).
You can provide multiple sort rules. The API applies them in order.

Find recently founded companies

Use comparison operators like > and < on numeric or date fields. This search finds companies founded after 2020, sorted by headcount.
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "field": "basic_info.year_founded",
      "type": ">",
      "value": 2020
    },
    "sorts": [{"column": "headcount.total", "order": "desc"}],
    "limit": 2,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "basic_info.year_founded",
      "headcount.total",
      "locations.hq_country"
    ]
  }'
Response trimmed for clarity.

Paginate through results

When your search matches more companies than your limit, use cursor-based pagination to walk through all pages. First page: send your normal search request.
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "field": "locations.hq_country",
      "type": "in",
      "value": ["USA"]
    },
    "sorts": [{"column": "crustdata_company_id", "order": "asc"}],
    "limit": 100,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "basic_info.primary_domain"
    ]
  }'
Next page: take the next_cursor value from the response and pass it in your next request. Keep the same filters, sorts, limit, and fields.
curl --request POST \
  --url https://api.crustdata.com/company/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": {
      "field": "locations.hq_country",
      "type": "in",
      "value": ["USA"]
    },
    "sorts": [{"column": "crustdata_company_id", "order": "asc"}],
    "limit": 100,
    "fields": [
      "crustdata_company_id",
      "basic_info.name",
      "basic_info.primary_domain"
    ],
    "cursor": "PASTE_NEXT_CURSOR_VALUE_HERE"
  }'
Continue until next_cursor is null, which means you have reached the last page.

Filter operator reference

OperatorMeaningExample valueNotes
=Exact match"retool.com"Case-insensitive for text fields
!=Not equal"acquired"
>Greater than2020Numbers and date strings
<Less than10000Numbers and date strings
=>Greater than or equal"2024-01-01"Not >=
=<Less than or equal50000000Not <=
inValue is in list["USA", "GBR"]Case-sensitive. Matches if any array element matches any list value.
not_inValue is not in list["acquired"]
containsContains substring"AI"Text fields only
not_containsDoes not contain"test"Text fields only
is_nullField is nullNo value needed
is_not_nullField is not nullNo value needed
(.)Fuzzy text search"openai"Tolerates typos, matches word variants
[.]Exact token match"Software Development"No typos allowed, requires exact tokens
The operators >= and <= are not supported. Use => and =< instead.

Searchable fields

These are common fields that can be used in the field key of a filter condition. For the full schema, see the API reference.
Industry fields: basic_info.industries contains broad industry tags from multiple sources. taxonomy.linkedin_industry is the single primary LinkedIn industry label. Use basic_info.industries for broad filtering and taxonomy.linkedin_industry for precise LinkedIn-based segmentation.For cross-endpoint field differences (country formats, LinkedIn field paths, year_founded types), see Conventions.
FieldTypeSortableDescription
crustdata_company_idintegerYesCrustdata company ID
updated_atdatetimeYesLast record update time
indexed_atdatetimeYesLast search index time
metadata.growth_calculation_datedatetimeYesAnchor date for growth metrics
basic_info.company_idintegerYesInternal source company ID
basic_info.namestringYesCompany name
basic_info.primary_domainstringYesPrimary website domain
basic_info.websitestringNoFull website URL
basic_info.professional_network_urlstringNoLinkedIn company URL
basic_info.professional_network_idstringNoLinkedIn numeric company ID
basic_info.company_typestringNoe.g., "Privately Held", "Public Company"
basic_info.year_foundedstringYesYear founded (string, e.g., "2017")
basic_info.employee_count_rangestringYese.g., "201-500"
basic_info.marketsstring[]NoMarket tags
basic_info.industriesstring[]NoIndustry tags
revenue.estimated.lower_bound_usdintegerYesRevenue lower bound (USD)
revenue.estimated.upper_bound_usdintegerYesRevenue upper bound (USD)
revenue.acquisition_statusstringNoe.g., "acquired"
funding.total_investment_usdnumberYesTotal disclosed funding (USD)
funding.last_round_amount_usdnumberYesLast funding round amount (USD)
funding.last_fundraise_datedateYesLast funding date
funding.last_round_typestringNoe.g., "series_a", "series_b"
funding.investorsstring[]NoInvestor names
funding.tracxn_investorsstring[]NoTracxn investor names
headcount.totalintegerYesTotal employee count
roles.distributionobjectNoEmployee counts per role
roles.growth_6mobjectNo6-month role growth
roles.growth_yoyobjectNoYear-over-year role growth
locations.hq_countrystringYesHQ country (ISO3: "USA", "GBR")
locations.largest_headcount_countrystringYesCountry with most employees
locations.headquartersstringNoFull HQ location string
taxonomy.linkedin_industrystringNoPrimary LinkedIn industry label
taxonomy.crunchbase_categoriesstring[]NoCrunchbase category tags
followers.countintegerYesLinkedIn follower count
followers.mom_percentnumberNoMonth-over-month follower growth %
followers.qoq_percentnumberNoQuarter-over-quarter follower growth %
followers.six_months_growth_percentnumberNo6-month follower growth %
followers.yoy_percentnumberNoYear-over-year follower growth %
competitors.company_idsinteger[]NoCompetitor Crustdata IDs
competitors.websitesstring[]NoCompetitor domains
Use Autocomplete to discover exact values for fields like basic_info.industries, taxonomy.linkedin_industry, locations.hq_country, basic_info.company_type, and funding.last_round_type.

Response fields

Each company in the response can include these sections (depending on fields):
SectionKey fieldsDescription
basic_infoname, primary_domain, website, professional_network_url, year_foundedCore identity and profile
headcounttotalEmployee footprint
fundingtotal_investment_usd, last_round_amount_usd, investorsFunding and investor data
locationshq_country, hq_state, hq_cityHeadquarters location
taxonomylinkedin_industry, crunchbase_categories, linkedin_specialitiesIndustry and category tags
revenueestimated, public_markets, acquisition_statusRevenue and market data
hiringopenings_count, openings_growth_percentHiring demand
followerscount, mom_percent, yoy_percentSocial follower metrics
social_profilescrunchbase, twitter_urlThird-party profile links

Validation rules

Default/max limits and pagination behavior reflect current platform behavior. See the API reference for the formal OpenAPI contract.
RuleBehavior
filters is optionalOmitting filters matches all companies. Always use filters in production to control cost.
fields is optionalOmitting returns all fields (large payload). Always specify in production.
limit range1–1000. Default: 20.
sorts with paginationAlways include sorts when paginating to ensure stable result ordering.
cursor must match queryChanging filters, sorts, or fields between pages invalidates the cursor.

Errors

Common error responses for Search:
400 — Unsupported field
{
    "error": {
        "type": "invalid_request",
        "message": "Unsupported columns in conditions: ['nonexistent_field']",
        "metadata": []
    }
}
400 — Invalid operator
{
    "error": {
        "type": "invalid_request",
        "message": "'filters.type' must be one of the supported operators. Got '>='.",
        "metadata": []
    }
}
Use => for greater-than-or-equal and =< for less-than-or-equal. The operators >= and <= are not supported.
401 — Invalid API key
{
    "message": "Invalid API key in request"
}

API reference summary

DetailValue
EndpointPOST /company/search
AuthBearer token + x-api-version: 2025-11-01
Requestfilters (condition or group), fields, sorts, limit, cursor
Response{ companies, next_cursor, total_count, query }
PaginationCursor-based. Pass next_cursor in cursor. null = last page.
Empty result200 with "companies": []
Errors400 (bad field/operator), 401 (bad auth), 403 (permission/credits), 500 (server error)
For shared conventions, error handling, and retry guidance, see Conventions. See the full API reference for the complete OpenAPI schema.

What to do next

  • Enrich a company — use Company Enrich to get a detailed profile for a known company.
  • Discover filter values — use Autocomplete to find valid values before building search filters.
  • See more examples — browse company examples for ready-to-copy patterns.