Skip to main content

Documentation Index

Fetch the complete documentation index at: https://docs.crustdata.com/llms.txt

Use this file to discover all available pages before exploring further.

How to paginate, sort, select fields, and aggregate results in Search Jobs. For filter grammar and example queries, see Filters & recipes. For the full field catalog and errors, see Reference.
Replace YOUR_API_KEY in each example with your actual API key. All requests require the x-api-version: 2025-11-01 header.

Sorting

sorts is an ordered array. Each item has a column and order ("asc" or "desc"). Sorts apply in array order — the first sort is the primary key, the second breaks ties, and so on.
{
    "sorts": [
        { "column": "metadata.date_added", "order": "desc" },
        { "column": "company.headcount.total", "order": "desc" }
    ]
}
Sort allowlist is narrower than filter allowlist. Sort only works on numeric, date, and a small set of scalar fields. Sorting on text fields like job_details.title, job_details.category, or company.basic_info.name returns Unsupported columns in conditions.

Sortable fields

The following indexed fields are verified sortable:
  • metadata.date_added
  • metadata.date_updated
  • company.headcount.total
  • company.followers.count
  • company.revenue.estimated.lower_bound_usd
  • company.revenue.estimated.upper_bound_usd
  • company.funding.total_investment_usd
  • company.funding.valuation_usd
  • company.funding.last_fundraise_date
  • company.funding.num_funding_rounds
Common sort choices:
  • Newest postings first{ "column": "metadata.date_added", "order": "desc" }
  • Biggest companies first{ "column": "company.headcount.total", "order": "desc" }
  • Most followed companies first{ "column": "company.followers.count", "order": "desc" }
  • Highest-funded companies first{ "column": "company.funding.total_investment_usd", "order": "desc" }

Pagination

Pagination is cursor-based. Each response returns a next_cursor (or null when you reach the end). To fetch the next page, resend the original request body with cursor set to the previous next_cursor.
1

Fetch the first page

Omit cursor and set limit to your page size (max 1000).
2

Walk forward

Take next_cursor from the response and pass it back as cursor in the next request. Keep filters, sorts, and fields identical — if you change them, the cursor becomes meaningless.
3

Stop when `next_cursor` is null

A null cursor means you’ve reached the end of the result set.

Consistency between pages

Current platform behavior — best-effort, not strict snapshot. A cursor is consistent with respect to the filter, sort, and field selection you sent on the first page, so the same query will keep paging forward over a coherent result stream. However, because the underlying indexed dataset is continuously updated, new jobs indexed between page requests can cause minor drift in total_count and in the exact position of individual rows. Treat pagination as best-effort, not a strict snapshot.For bulk exports where every row matters:
  • Constrain your filter to a bounded date window (for example metadata.date_added >= 2025-01-01 AND < 2025-07-01) so newly indexed jobs outside the window do not affect the walk, and
  • Re-run the full walk periodically and diff against the prior snapshot using crustdata_job_id as the dedupe key.

Dataset freshness and lifecycle

What the indexed Jobs dataset represents. The Search Jobs dataset is a rolling index of job listings discovered from the web, refreshed on an ongoing basis. Each row has:
  • metadata.date_added — when Crustdata first saw the listing.
  • metadata.date_updated — most recent refresh.
Closed or removed listings are not guaranteed to disappear from the index immediately. To approximate “currently hiring” queries, filter on a recent metadata.date_added or metadata.date_updated window (for example, within the last 30 days) and pair it with the hiring company’s firmographics. For alerting or repeated exports, keep your date windows bounded and dedupe rows with crustdata_job_id.

Date filter semantics

Dates and timezones. When you pass a date-only value like "2025-01-01", the backend interprets it as 2025-01-01T00:00:00 in UTC. Ranges using => are inclusive of the boundary and < is exclusive, so "metadata.date_added" >= "2025-01-01" AND < "2025-07-01" covers every listing indexed between Jan 1 (inclusive) and Jul 1 (exclusive) in UTC. Pass full timestamps like "2025-01-01T08:00:00" when you need finer precision.

Fetch page 2

{
    "filters": {
        "field": "company.basic_info.company_id",
        "type": "=",
        "value": 631394
    },
    "fields": ["job_details.title"],
    "limit": 1,
    "cursor": "H4sIANBG1mkC_xXMOQ4CMQxA0auMUk9hx3YScxWERs6CpkBEzFIgxN0J1W-e_se9zra9l9X21V0mx0kjMgvdq4dYPZGgclOTlLEZl2bJG_lcdVSqFa-okDlwo1qbmye39-0YryvGKBIwsQLAPDGCkAS6DXL0wx5L6efzL2MC_P4A250zQYoAAAA="
}

Field selection

Use fields to return only the dot-paths you need. The top-level groups are crustdata_job_id, job_details, company, location, content, metadata. You can request:
  • A whole group"company" returns every company.* sub-object.
  • A sub-object"company.basic_info" returns only the basic info block.
  • A single field"company.basic_info.name" returns just the name.
{
    "fields": [
        "job_details.title",
        "job_details.url",
        "company.basic_info.name",
        "company.basic_info.primary_domain",
        "location.raw",
        "metadata.date_added"
    ]
}
Recommended default field set for most dashboards: ["job_details.title", "job_details.category", "job_details.url", "company.basic_info.name", "company.basic_info.primary_domain", "location.raw", "metadata.date_added"].

Aggregations

Aggregations let you roll up results without returning individual job rows. Set limit: 0 when you only want aggregation output. Two types are supported:
  • count — returns the total number of jobs matching filters.
  • group_by — buckets the results by column and returns per-bucket counts.

AggregationRequest schema

FieldTypeRequiredDescription
typestring (enum)Yes"count" for a simple total, "group_by" to bucket by column.
columnstringRequired for group_byDot-path to group by. Must be in the Groupable fields allowlist.
aggstring (enum)Required for group_bySub-aggregation inside each bucket. Currently only "count" is supported.
sizeintegerNo (default 100)Maximum number of buckets to return. Min 1, max 1000.
Each AggregationResponseItem echoes type and column, then carries:
  • value (integer) — populated for count aggregations. The total match count.
  • buckets (array) — populated for group_by aggregations. Each bucket has a key, count, and a metadata object whose keys depend on the grouped column. See Aggregation bucket metadata.
You can include multiple aggregations in a single request; the response returns them in aggregations[] in the same order you sent them.

Count all Engineering jobs

curl --request POST \
  --url https://api.crustdata.com/job/search \
  --header 'authorization: Bearer YOUR_API_KEY' \
  --header 'content-type: application/json' \
  --header 'x-api-version: 2025-11-01' \
  --data '{
    "filters": { "field": "job_details.category", "type": "=", "value": "Engineering" },
    "limit": 0,
    "aggregations": [ { "type": "count" } ]
  }'

Top companies indexing “Software Engineer” listings (bounded window)

curl --request POST \
  --url https://api.crustdata.com/job/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": "job_details.title",   "type": "=",  "value": "Software Engineer" },
        { "field": "metadata.date_added", "type": "=>", "value": "2025-01-01" },
        { "field": "metadata.date_added", "type": "<",  "value": "2026-01-01" }
      ]
    },
    "limit": 0,
    "aggregations": [
      {
        "type": "group_by",
        "column": "company.basic_info.company_id",
        "agg": "count",
        "size": 5
      }
    ]
  }'

Groupable fields

group_by.column is restricted to the following indexed fields:
  • company.basic_info.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
Sending any other column returns 400 with Unsupported aggregation column: '...'. Supported: ....

Next steps

  • Filters & recipes — filter grammar, operators, and example queries.
  • Reference — full field catalog, id map, bucket metadata, and errors.
  • Search Jobs — back to the main Search page.