Use this when you need to find, segment, or count job listings across the full Crustdata job dataset — for hiring-trend analysis, building target account lists from recently indexed hiring activity, monitoring specific roles, or powering a dashboard.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.
metadata.date_added is when Crustdata first indexed the listing,
not the employer-posted timestamp. Every query in this page that
filters on metadata.date_added is asking about indexing time, not
the employer’s actual publication date. Treat this endpoint as a query
interface over Crustdata’s indexed dataset, not as a direct poll of an
employer-managed listings feed.Replace
YOUR_API_KEY in each example with your actual API key. All
requests require the x-api-version: 2025-11-01 header.Job record mental model
Every job listing returned by Search Jobs is a singleJob object with five
top-level groups:
crustdata_job_idandjob_details— The stable job id plus the posting’s own metadata: title, category, URL, workplace type, and number of openings.company— The hiring company’s firmographics at index time: basic info, headcount, followers, revenue, funding, locations, and competitors. No extra/company/enrichcall required.location— The job’s advertised location (city, state, country, raw string), not the company HQ.content— Full job description text. Use the(.)filter operator oncontent.descriptionto keyword-hunt.metadata— Indexing timestamps:date_addedfor when the listing first appeared anddate_updatedfor the most recent refresh. These are your primary sort and filter columns for recent windows.
Jobs ID cheat sheet. The Jobs APIs use three id concepts — keep them straight:
crustdata_job_id— the Crustdata job identifier. Returned on everyJob. Use it as your dedupe key.company.basic_info.crustdata_company_id— the Crustdata company identifier returned on everyJob.company.basic_info.company_id(filter alias) — the dot-path used infiltersandaggregations.columnfor indexed Search Jobs. It points to the same integer ascompany.basic_info.crustdata_company_id. This alias is not sortable; for deterministic pagination, sort onmetadata.date_addedinstead.
group_by on company.basic_info.company_id, each bucket also returns metadata.company_name, metadata.company_website_domain, and metadata.linkedin_id for labeling.At a glance
| Detail | Value |
|---|---|
| Endpoint | POST https://api.crustdata.com/job/search |
| Auth | Authorization: Bearer YOUR_API_KEY |
| API version | x-api-version: 2025-11-01 header (required) |
| Body | Required. Send {} to match the whole dataset; every realistic query uses filters. |
| Body keys | filters, cursor, limit (0–1000, default 20), sorts, fields, aggregations — all optional |
| Response | { "job_listings": [ Job, ... ], "next_cursor": string?, "total_count": integer?, "aggregations"?: [ ... ] } |
| Errors | 400 invalid request · 401 unauthorized · 500 internal |
Guaranteed contract vs current behavior
| Topic | What it means |
|---|---|
| Endpoint, HTTP method, auth headers | POST /job/search, bearer auth, x-api-version: 2025-11-01. |
| Request body shape | Optional filters, cursor, limit, sorts, fields, aggregations. filters is a SearchCondition or a SearchConditionGroup. |
| Response body shape | { "job_listings", "next_cursor", "total_count", "aggregations"? }. Aggregation-only queries return "job_listings": []. |
| Supported operators | =, !=, <, =<, >, =>, in, not_in, is_null, is_not_null, (.), [.]. See Filter operators. |
limit bounds and default | Minimum 0, maximum 1000, default 20. Set limit: 0 when you only want aggregations. |
| Error status codes | 400, 401, 500. |
| Indexed-field allowlist | Only indexed fields can appear in filters, sorts, or aggregations.column. See Reference for the detailed catalog, or Common indexed fields for the most-used subset. |
| Pricing and rate limits | See Pricing and Rate limits for current numbers. |
Filters & recipes
Filter grammar, operators, and example queries like “SDR hiring in
mid-market”, “companies that closed Series B”, full-text keyword
hunts.
Pagination & sorting
Sorting, cursor-based pagination, field selection, and
aggregations with
count and group_by.Reference
Common indexed fields, annotated
Job example, full field catalog,
id map, bucket metadata, errors.Request body
| Parameter | Type | Required | Default | Description |
|---|---|---|---|---|
filters | object | No | — | Single SearchCondition or nested SearchConditionGroup. Omit to match all indexed jobs. |
cursor | string | No | — | Opaque cursor from a prior response’s next_cursor. Pass it to fetch the next page with the same filter, sort, and field set. |
limit | integer | No | 20 | Rows per page. Min 0, max 1000. Use 0 for aggregation-only queries. |
sorts | array of SearchSort | No | — | Ordering rules. Each item has column (dot-path) and order (asc or desc). Sorts are applied in array order. |
fields | string[] | No | all fields | Dot-paths to include in each returned job. Omit to return everything. Always specify fields in production for smaller payloads and faster responses. |
aggregations | array of AggregationRequest | No | — | Roll-up queries. Supports count and group_by. Use with limit: 0 if you only want counts. |
Response body
| Field | Type | Description |
|---|---|---|
job_listings | Job[] | Matching job listings for the current page. Empty array [] when limit is 0 or when an aggregation-only query is made. |
next_cursor | string or null | Opaque cursor to fetch the next page. null when there are no more pages. |
total_count | integer or null | Total number of jobs matching the filter across all pages. Can be null for very broad queries where computing an exact total would be prohibitively expensive — never assume it is populated. |
aggregations | array | Aggregation results, present only when the request included an aggregations array. |
Rate limits and credits
Current pricing for indexed Jobs Search:
Pricing:
0.03 credits per result returned.
A request with no results does not consume credits.Default
rate-limit is 15 requests per minute. Send an email to
gtm@crustdata.co to discuss higher limits if
needed for your use case.Your first search: filter by company and title
Find the most recent Software Engineer listings at Stripe (filtered via thecompany.basic_info.company_id alias, which maps to crustdata_company_id = 631394).
Which search pattern should I use?
- I want to explore the dataset
- I only have a company domain or name
- I want only counts, not job rows
- I want a repeatable account list
- I want fresh live listings for one company
Use Search Jobs. You can slice millions of indexed job listings by
company, title, category, location, date, or any other indexed field — and
roll up results with
count or group_by aggregations. Pair it with
cursor-based pagination to walk through large result sets.What’s next
- Learn filter patterns — see Filters & recipes for filter grammar, operators, and example queries.
- Paginate and aggregate — see Pagination & sorting for cursor pagination, sorting, field selection, and aggregations.
- Look up fields — see Reference for the full
Jobcatalog, id map, bucket metadata, and errors. - Fetch fresh listings for one company — see Live Search.
- Inspect the full schema — read the OpenAPI reference.

