---
title: "Search the indexed job dataset"
method: POST
path: "/job/search"
tags: ["Job APIs", "Search APIs"]
---

# Search the indexed job dataset

`POST /job/search`

Search the Crustdata job dataset using filter conditions. Each result includes
the job's details (title, category, URL, openings), the hiring company's core
firmographics (basic info, headcount, followers, revenue, funding, competitors),
the job location, full job description text, and metadata timestamps.

<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>

Supports complex AND/OR filter logic, cursor-based pagination, sorting, field
selection, aggregations (count and group_by), and geographic radius filtering
on `location` with the `geo_distance` and `geo_exclude` operators. Only indexed
fields are filterable and sortable — see the `field` description on
`SearchCondition` for the full list.

## Headers

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

## Request body

- JobSearchRequest — Request body for searching the indexed job dataset with filters, pagination, sorting, field selection, and aggregations.
  - `filters` union — Search filter conditions. Can be a single condition or a nested group combined with AND/OR logic. Only indexed fields are filterable — see `SearchCondition.field` for the full list.
    - 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 — Opaque pagination cursor returned in a prior response's `next_cursor` field. Pass this to fetch the next page of results with the same filter, sort, and field selection.
  - `limit` integer — Maximum number of job listings to return per page. Set to 0 when you only want aggregations.
  - `sorts` SearchSort[] — Sort specifications for ordering results. Sorts are applied 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 each job listing. Use dot-notation for nested fields (e.g., "job_details.title", "company.basic_info.name"). If omitted, all available fields are returned. Valid top-level groups: `crustdata_job_id`, `job_details`, `company`, `location`, `content`, `metadata`. Nested fields are supported (e.g., `company.basic_info`, `company.headcount`, `company.funding`).
  - `aggregations` AggregationRequest[] — Aggregation queries to run alongside the search. Set `limit: 0` if you want only aggregation results and no job rows.
    - `type` 'count' | 'group_by', required — Aggregation type.
    - `field` string, nullable — Field (dot-path) to group results by. Required when `type` is `group_by`; omitted for `count`. Supported fields: `company.basic_info.company_id`, `company.basic_info.crustdata_company_id`, `company.basic_info.industries`, `company.basic_info.primary_domain`, `company.funding.last_round_type`, `company.headcount.range`, `company.locations.country`, `job_details.category`, `job_details.title`, `job_details.workplace_type`, `location.country`.
    - `agg` string, nullable — Sub-aggregation to compute inside each bucket. Required for `group_by`. Currently only `count` is supported.
    - `size` integer — Maximum number of buckets to return for a `group_by` aggregation.

## Response `200`

Jobs matching the search criteria with pagination cursor and total count

- JobSearchResponse — Paginated response from the indexed job search endpoint.
  - `job_listings` Job[], required — Job listings matching the search criteria for the current page. Empty when `limit` is 0 or when an aggregation-only query is made.
    - `crustdata_job_id` integer — Unique Crustdata internal job identifier.
    - `job_details` object — Core information about the job posting itself.
      - `job_id` integer, nullable — Job identifier (currently mirrors `crustdata_job_id`).
      - `title` string, nullable — Job title as posted.
      - `category` string, nullable — High-level job category (e.g., Engineering, Sales, Operations, Consultancy, Others).
      - `workplace_type` string, nullable — Workplace type if provided (e.g., Remote, Hybrid, On-site). May be empty.
      - `url` string, nullable — Canonical URL for the job posting.
      - `reposted_job` boolean, nullable — Whether the posting was detected as a repost of a prior listing.
      - `number_of_openings` integer, nullable — Number of openings the posting is hiring for.
    - `company` object — Hiring company's firmographics at the time of indexing.
      - `basic_info` object — Core identifiers, domain, industries.
        - `crustdata_company_id` integer, nullable — Unique Crustdata internal company identifier.
        - `name` string, nullable — Official company name.
        - `primary_domain` string, nullable — Primary web domain for the company.
        - `website` string, nullable — Company website URL.
        - `professional_network_id` string, nullable — Identifier for the company on the professional network profile source.
        - `industries` string[], nullable — Industry classifications assigned to the company.
      - `locations` object — Company's registered or primary office location.
        - `country` string, nullable — ISO country code for the primary office.
        - `state` string, nullable — State or region for the primary office.
        - `city` string, nullable — City for the primary office.
        - `street_address` string, nullable — Full street address for the primary office.
      - `headcount` object — Company headcount at the time of indexing.
        - `total` integer, nullable — Total current headcount across all offices.
        - `range` string, nullable — Headcount bracket (e.g., "51-200", "5001-10000").
        - `largest_headcount_country` string, nullable — ISO country code where the company has the most employees.
      - `followers` object — Public profile follower counts.
        - `count` integer, nullable — Total followers of the company's public profile.
      - `revenue` object — Estimated revenue and public market signals.
        - `estimated` object — Estimated annual revenue range in USD.
          - `lower_bound_usd` integer, nullable — Lower bound of the estimated annual revenue range, in USD.
          - `upper_bound_usd` integer, nullable — Upper bound of the estimated annual revenue range, in USD.
        - `public_markets` object, nullable — Public market information when the company is listed.
          - `stock_symbols` string[], nullable — Stock ticker symbols associated with the company.
          - `fiscal_year_end` string, nullable — Fiscal year end if reported.
        - `acquisition_status` string, nullable — Acquisition status if known (e.g., acquired, merged).
      - `funding` object — Venture funding details.
        - `total_investment_usd` number, nullable — Total capital raised to date, in USD.
        - `valuation_usd` number, nullable — Most recent valuation in USD.
        - `last_fundraise_date` string, nullable — Date of the most recent funding event (ISO 8601).
        - `last_round_type` string, nullable — Type of the most recent funding round (e.g., seed, series_a, series_b, secondary_market).
        - `num_funding_rounds` integer, nullable — Total number of funding rounds recorded.
        - `investors` string[], nullable — Known investors across all rounds.
      - `competitors` object — Known competitor companies.
        - `websites` string[], nullable — List of competitor website URLs.
    - `location` object — Job's advertised location. The `city`, `state`, and `country` fields are derived by geocoding the raw location string, so their values are normalized place names (e.g. `United States` rather than the raw text's country wording).
      - `raw` string, nullable — Raw location string as advertised on the job posting.
      - `city` string, nullable — City from geocoding the raw location. Empty string when the raw location resolves to a broader area than a city (e.g. a metro area).
      - `district` string, nullable — District or borough from geocoding, when the location resolves to that granularity.
      - `state` string, nullable — State or province from geocoding the raw location.
      - `country` string, nullable — Normalized country name from geocoding the raw location.
      - `pincode` string, nullable — Postal or zip code if available.
    - `content` object — Text content of the job posting.
      - `description` string, nullable — Full job description as published.
    - `metadata` object — Indexing timestamps.
      - `date_added` string, nullable — When the job listing was first indexed (ISO 8601).
      - `date_updated` string, nullable — When the job listing was last refreshed (ISO 8601).
  - `next_cursor` string, nullable — Opaque cursor for fetching the next page of results. Pass this value as `cursor` in the next request. `null` when there are no more pages.
  - `total_count` integer, nullable — Total number of job listings matching the query across all pages.
  - `aggregations` AggregationResponseItem[], nullable — Aggregation results, present only when the request included an `aggregations` array.
    - `type` 'count' | 'group_by' — Echoed aggregation type.
    - `field` string, nullable — Echoed field name (`null` for `count`).
    - `value` integer, nullable — Total count matching the filter. Present only for `count` aggregations.
    - `buckets` AggregationBucket[], nullable — Group buckets. Present only for `group_by` aggregations. Ordered by descending count.
      - `key` union — Bucket key value (the grouped field's value — integer, string, or array element).
        - string
        - integer
        - number
      - `count` integer — Number of job listings in this bucket.
      - `metadata` object, nullable — Additional context for the bucket key. Only returned for fields that have metadata configured (e.g. `company.basic_info.company_id`, `company.basic_info.crustdata_company_id`, `company.basic_info.primary_domain`).
        - `company_name` string, nullable — Company name for the grouped company.
        - `crustdata_company_id` integer, nullable — Crustdata internal company identifier, when applicable to the grouped field.
        - `company_website_domain` string, nullable — Primary web domain for the grouped company.
        - `linkedin_id` string, nullable — Professional-network identifier for the grouped company.

## Other responses

- `400` — Invalid search request - the request body failed validation (bad limit, missing or malformed fields, or an unrecognized parameter).
- `401` — Unauthorized - invalid or missing API key
- `500` — Internal server error - returned when the query cannot be executed, including when a filter or aggregation references an unsupported field, when a `geo_distance`/`geo_exclude` value is malformed or targets a non-geo field, or when a `location` string cannot be geocoded.

---

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