Two endpoints for finding jobs: a quick GET keyword search with facets and a typed POST search with full inclusion/exclusion filters and range support.
Two search endpoints — quick keyword search vs. typed search with facets — plus a single-job lookup by id.
Quick search — GET /api/jobs. Simple query-string search with comma-separated filters. Best for lightweight integrations and URL-shareable queries.
Advanced search — POST /api/jobs/search. Typed JSON body with inclusion/exclusion filters, range filters, and multi-value text queries. Best for filter UIs and programmatic search.
Get a job — GET /api/jobs/{id}. Re-fetch a single job by the id returned on any search or feed result. Free — deducts no credits.
All three return JobDto objects — see the Feed page for the full field reference.
Full request/response reference and a live “Try it” playground live on the dedicated pages below.
Quick search
GET /api/jobs — simple query-string search. Best for lightweight integrations and URL-shareable queries.
Advanced search
POST /api/jobs/search — typed JSON body with inclusion/exclusion filters, range filters, and multi-value text queries. Best for filter UIs and programmatic search.
Get a job
GET /api/jobs/{id} — fetch a single job by id (the id from any search or feed result). Free — deducts no credits.
By default a query is a broad relevance search: each entry is matched
against the job title, company name, popular skills, and summary, with typo
tolerance. That maximises recall but means a query like data engineer can also
surface roles whose title isn’t “data engineer” — the words appear elsewhere in
the listing.
Wrap a query in double quotes to switch that entry to a strict match: the
exact phrase must appear, contiguously, in the job title only. Typo
tolerance and partial-word matching are turned off. Use this when the query is a
job-title filter and broad matches are noise.
Only jobs whose title contains “Quantitative Developer” (or “Quant
Developer”) are returned; a “Senior Android Engineer” whose description mentions
software won’t match. Multiple quoted entries are OR’d, so the example above
returns titles matching either phrase.You can mix quoted and unquoted entries — each is evaluated independently and
the results are combined:
On GET /api/jobs the same rule applies to the q parameter — pass the quotes
in the value (?q="Quantitative Developer").
A request may carry at most 5 positive terms in queries. Sending more
returns a 400 (rather than silently ignoring the extras) so you always know
exactly what was searched. Negative - exclusions don’t count toward the limit.
By default every job carries all of its fields. To shrink the response, pass
include_fields to keep only the non-core fields you actually need — the
lightweight core fields (id, title, company, locations, compensation, dates,
source, work-auth flags, …) are always returned.
include_fields
Result
omitted / null
Full job — every field (the default, unchanged).
["description","benefits"]
Core +description and benefits only.
[] (empty array)
Core fields only.
The gateable non-core fields are description, summary, qualifications,
responsibilities, and benefits. On GET /api/jobs pass a comma-separated
string (?include_fields=description,benefits); on POST /api/jobs/search pass a
JSON array. To get core fields only from the GET endpoint, send the empty value
?include_fields=. Unknown names are silently dropped, and any non-core field you
don’t request comes back empty ("" / []) rather than absent — the same
present-but-empty convention the facets use.The heavy description body dominates response size, so dropping it is the
single biggest win for high-volume search.
The response includes a facets object with server-computed aggregations. The set of facets is controlled by the include_facets request parameter; when omitted the server returns a low-cardinality default subset to keep responses fast.
skills is returned; unknown names are silently dropped.
On GET /api/jobs pass a comma-separated string (?include_facets=skills,industries); on POST /api/jobs/search pass a JSON array ("include_facets": ["skills", "industries"]). To skip facets from the GET endpoint, send the empty value ?include_facets=.
Facet values for enum fields reflect the lowercased canonical values stored in the index, sorted by count descending. skills is faceted on its display-cased values.Counts are bounded by Typesense’s top_values strategy, so long-tail buckets may be approximate — exact totals come from the total field, not from summing facet counts.Use facet values to power filter UIs. Since all filter fields are case-insensitive, you can pass facet key values directly back as filter values.
Send the canonical value listed below. Filter inputs are matched case-insensitively and common variants (e.g. sr → senior, WFH → remote) are normalized server-side, so most reasonable strings will resolve to the right bucket.
All 57 ATS / job-board providers Jobo currently ingests. Use the provider_id in the sources filter (e.g. "sources": ["greenhouse", "lever"]); the same value comes back on the source field of every JobDto and in the facets.sources bucket.