Skip to main content
Two search endpoints — quick keyword search vs. typed search with facets — plus a single-job lookup by id.
  • Quick searchGET /api/jobs. Simple query-string search with comma-separated filters. Best for lightweight integrations and URL-shareable queries.
  • Advanced searchPOST /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 jobGET /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.

Endpoints

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.

Filter recipes

Basic text search with location

Search for jobs by keyword in one or more cities:
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.

Title-scoped exact match (quoted phrases)

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

Skill include/exclude filtering

Find jobs requiring Python or Go but not PHP:

Company filtering

Search only at specific companies, or exclude staffing agencies:

Salary range + experience level

Find senior or principal roles paying 150k150k–250k:
For open-ended ranges, omit one bound:

Remote jobs posted recently

Bounded posting date window

Use posted_after / posted_before to bound results by the employer posting date.

Full combination query

Combine every filter type for a highly targeted search:

Selecting fields

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

Facets

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.

Available facets

Controlling the facet set

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

Example — default response

Example — opting in to skills + industries

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.

Enum reference

Send the canonical value listed below. Filter inputs are matched case-insensitively and common variants (e.g. srsenior, WFHremote) are normalized server-side, so most reasonable strings will resolve to the right bucket.

work_models

employment_types

experience_levels

Source values

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.