> ## Documentation Index
> Fetch the complete documentation index at: https://jobo.world/docs/llms.txt
> Use this file to discover all available pages before exploring further.

# Jobs Search

> 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](/api-reference/jobs-search/search-jobs-via-query-parameters)** — `GET /api/jobs`. Simple query-string search with comma-separated filters. Best for lightweight integrations and URL-shareable queries.
* **[Advanced search](/api-reference/jobs-search/search-jobs-via-structured-request-body)** — `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](/api-reference/jobs-search/get-a-single-job-by-id)** — `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](/api-reference/feed/jobs-feed#jobdto-schema) — 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.

<CardGroup cols={2}>
  <Card title="Quick search" icon="magnifying-glass" href="/api-reference/jobs-search/search-jobs-via-query-parameters">
    `GET /api/jobs` — simple query-string search. Best for lightweight integrations and URL-shareable queries.
  </Card>

  <Card title="Advanced search" icon="filter" href="/api-reference/jobs-search/search-jobs-via-structured-request-body">
    `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.
  </Card>

  <Card title="Get a job" icon="briefcase" href="/api-reference/jobs-search/get-a-single-job-by-id">
    `GET /api/jobs/{id}` — fetch a single job by id (the `id` from any search or feed result). Free — deducts no credits.
  </Card>
</CardGroup>

***

## Filter recipes

### Basic text search with location

Search for jobs by keyword in one or more cities:

```json theme={null}
{
  "queries": ["data engineer"],
  "locations": ["Seattle", "Austin"],
  "page_size": 10
}
```

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.

```json theme={null}
{
  "queries": ["\"Quantitative Developer\"", "\"Quant Developer\""]
}
```

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:

```json theme={null}
{
  "queries": ["\"Quant Developer\"", "machine learning engineer"]
}
```

On `GET /api/jobs` the same rule applies to the `q` parameter — pass the quotes
in the value (`?q="Quantitative Developer"`).

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

### Skill include/exclude filtering

Find jobs requiring Python or Go but not PHP:

```json theme={null}
{
  "queries": ["backend developer"],
  "skills": {
    "include": ["python", "go"],
    "exclude": ["php"]
  }
}
```

### Company filtering

Search only at specific companies, or exclude staffing agencies:

```json theme={null}
{
  "queries": ["product manager"],
  "companies": {
    "include": ["Google", "Meta", "Apple", "Amazon"]
  }
}
```

```json theme={null}
{
  "queries": ["software engineer"],
  "companies": {
    "exclude": ["Acme Staffing", "Generic Recruiting Co"]
  }
}
```

### Salary range + experience level

Find senior or principal roles paying $150k–$250k:

```json theme={null}
{
  "experience_levels": ["senior"],
  "salary_usd": { "min": 150000, "max": 250000 },
  "employment_types": ["full-time"]
}
```

For open-ended ranges, omit one bound:

```json theme={null}
{
  "salary_usd": { "min": 200000 }
}
```

### Remote jobs posted recently

```json theme={null}
{
  "queries": ["machine learning engineer"],
  "work_models": ["remote"],
  "posted_after": "2026-02-01T00:00:00Z"
}
```

### Bounded posting date window

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

```json theme={null}
{
  "queries": ["backend engineer"],
  "posted_after": "2026-02-01T00:00:00Z",
  "posted_before": "2026-03-01T00:00:00Z"
}
```

### Full combination query

Combine every filter type for a highly targeted search:

```json theme={null}
{
  "queries": ["backend engineer", "platform engineer"],
  "locations": ["San Francisco", "New York", "Seattle"],
  "skills": {
    "include": ["go", "rust", "kubernetes"],
    "exclude": ["php", "wordpress"]
  },
  "companies": {
    "exclude": ["Acme Staffing"]
  },
  "work_models": ["remote", "hybrid"],
  "employment_types": ["full-time"],
  "experience_levels": ["senior", "lead"],
  "salary_usd": { "min": 150000, "max": 300000 },
  "posted_after": "2026-01-15T00:00:00Z",
  "posted_before": "2026-06-01T00:00:00Z",
  "page": 1,
  "page_size": 50
}
```

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

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

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

| Response key       | Source field         | Notes                                                  |
| ------------------ | -------------------- | ------------------------------------------------------ |
| `work_model`       | `work_model`         | Default                                                |
| `experience_level` | `experience_level`   | Default                                                |
| `employment_type`  | `employment_type`    | Default                                                |
| `sources`          | `provider_id`        | Default                                                |
| `industries`       | `company_industries` | **Opt-in** — moderate cardinality                      |
| `skills`           | `all_skill_names`    | **Opt-in** — high cardinality, adds noticeable latency |

### Controlling the facet set

| `include_facets`       | Result                                                                           |
| ---------------------- | -------------------------------------------------------------------------------- |
| *omitted* / `null`     | Default subset (`work_model`, `experience_level`, `employment_type`, `sources`). |
| `["skills"]`           | Only `skills` is computed and returned.                                          |
| `[]` (empty array)     | No facets — `"facets": {}`.                                                      |
| `["skills","unknown"]` | `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=`.

### Example — default response

```json theme={null}
{
  "facets": {
    "experience_level": [
      { "key": "senior", "count": 4521 },
      { "key": "mid", "count": 3892 },
      { "key": "lead", "count": 1204 },
      { "key": "entry", "count": 987 },
      { "key": "executive", "count": 412 },
      { "key": "intern", "count": 43 }
    ],
    "work_model": [
      { "key": "remote", "count": 5230 },
      { "key": "hybrid", "count": 2847 },
      { "key": "onsite", "count": 1540 }
    ]
  }
}
```

### Example — opting in to skills + industries

```json theme={null}
{
  "queries": ["backend engineer"],
  "include_facets": [
    "work_model",
    "experience_level",
    "employment_type",
    "sources",
    "industries",
    "skills"
  ]
}
```

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. `sr` → `senior`, `WFH` → `remote`) are normalized server-side, so most reasonable strings will resolve to the right bucket.

### work\_models

| Value    | Meaning                                             |
| -------- | --------------------------------------------------- |
| `remote` | Fully remote; no expectation of being in an office. |
| `hybrid` | Mix of remote and in-office work.                   |
| `onsite` | On-site / in-person at a specific location.         |

### employment\_types

| Value        | Meaning                                                       |
| ------------ | ------------------------------------------------------------- |
| `full-time`  | Standard full-time permanent role.                            |
| `part-time`  | Part-time role with reduced hours.                            |
| `contract`   | Fixed-term or contractor engagement (incl. contract-to-hire). |
| `internship` | Internship, co-op, or apprenticeship.                         |
| `freelance`  | Freelance / self-employed / gig work.                         |
| `temporary`  | Short-term or seasonal role.                                  |

### experience\_levels

| Value       | Meaning                                                 |
| ----------- | ------------------------------------------------------- |
| `intern`    | Interns, trainees, apprentices.                         |
| `entry`     | Entry-level / junior / new graduate.                    |
| `mid`       | Mid-level / intermediate individual contributor.        |
| `senior`    | Senior individual contributor (incl. staff, principal). |
| `lead`      | Tech lead or first-line manager.                        |
| `executive` | Director, VP, C-level, head-of.                         |

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

| `provider_id`     | Provider             |
| ----------------- | -------------------- |
| `adpmyjobs`       | ADP MyJobs           |
| `adpworkforcenow` | ADP Workforce Now    |
| `applicantpro`    | ApplicantPro         |
| `ashby`           | Ashby                |
| `bamboohr`        | BambooHR             |
| `breezy`          | Breezy HR            |
| `careerplug`      | CareerPlug           |
| `careerpuck`      | Careerpuck           |
| `comeet`          | Comeet               |
| `csod`            | Cornerstone OnDemand |
| `dayforce`        | Dayforce             |
| `dover`           | Dover                |
| `eightfold`       | Eightfold            |
| `freshteam`       | Freshteam            |
| `gem`             | Gem                  |
| `gohire`          | GoHire               |
| `greenhouse`      | Greenhouse           |
| `hibob`           | HiBob                |
| `hirebridge`      | HireBridge           |
| `hirehive`        | HireHive             |
| `hireology`       | Hireology            |
| `hiringthing`     | HiringThing          |
| `homerun`         | Homerun              |
| `icims`           | iCIMS                |
| `isolved`         | iSolved              |
| `jazzhr`          | JazzHR               |
| `jobscore`        | JobScore             |
| `jobvite`         | Jobvite              |
| `joincom`         | Join.com             |
| `kula`            | Kula                 |
| `lever`           | Lever                |
| `manatal`         | Manatal              |
| `oraclecloud`     | Oracle Cloud         |
| `pageup`          | PageUp               |
| `paycom`          | Paycom               |
| `paycor`          | Paycor               |
| `paylocity`       | Paylocity            |
| `personio`        | Personio             |
| `phenompeople`    | Phenom               |
| `pinpoint`        | Pinpoint             |
| `polymer`         | Polymer              |
| `recooty`         | Recooty              |
| `recruitee`       | Recruitee            |
| `rippling`        | Rippling             |
| `rival`           | Rival                |
| `smartrecruiters` | SmartRecruiters      |
| `successfactors`  | SAP SuccessFactors   |
| `taleo`           | Oracle Taleo         |
| `talnet`          | TalNet (Oleeo)       |
| `teamtailor`      | Teamtailor           |
| `trakstar`        | Trakstar Hire        |
| `trinet`          | TriNet               |
| `ultipro`         | UltiPro (UKG Pro)    |
| `werecruit`       | WeRecruit            |
| `workable`        | Workable             |
| `workday`         | Workday              |
| `zohorecruit`     | Zoho Recruit         |
