Both are page-based and ranked by relevance unless you set
sort. They reach at most 100,000 results deep (page × page_size, see Pagination). To export the whole corpus, use the feed: it costs the same per job, and its cursor doesn’t skip or repeat jobs as records change.
Parameter equivalence
- Unknown parameters and body fields are ignored, and listed in
warnings(codeunknown_request_fields) and theX-Jobo-Warningsheader. POSTarrays are not comma-split."employment_types": ["full-time,contract"]is one literal value and matches nothing; write["full-time", "contract"].GETfilters only include. To exclude skills, industries, company categories, job categories, job subcategories or occupations, use theexcludeside of thePOSTobject.
How text queries match
A
- entry with several words excludes jobs that contain any of them. Neither mode searches the full description. Set search_description=false when you pass exact job titles: Android Developer then also finds Android Engineer, but not jobs that only mention Android as a skill or in the summary.
With the default sort, jobs that match every word of a query rank first. Partial matches fill the tail only when a query has no full match inside your filters (a short posted_after range, for example), so take results from the top.
Quoted phrases match titles only
GET /api/jobs, put the quotes inside the value: ?q="Quantitative Developer".
queries takes at most 10 positive entries. More returns a 400 instead of dropping the extras. Negative - entries don’t count toward the limit.Recipes
The Python samples use the Python SDK and reuse theclient from the first recipe. Parameters the 4.0.0 SDKs don’t send, such as sort and the occupation filters, have curl or JSON samples only.
Keyword plus location
location and locations use the same resolver as GET /api/locations/geocode, so you can check how a string will be read before you search. See Resolve locations.
Remote senior roles in a salary band
senior, not senior level.
Since 4.0.0, the client enums (
WorkModel, EmploymentType, ExperienceLevel) send canonical values: EmploymentType.FULL_TIME sends full-time, and ExperienceLevel.INTERN and EmploymentType.FREELANCE exist. On 3.x and earlier, pass string literals instead of the enums (Upgrading to 4.0.0).Include and exclude skills
POST-only. include entries are OR’d, and jobs matching any exclude entry are removed. companies, industries, company_categories, job_categories, job_subcategories and occupation_ids take the same object.
Target or exclude specific employers
companies works on POST only. Each entry is matched by its form:
- A domain ignores a leading
www.but not other subdomains:careers.fedex.comdoesn’t matchfedex.com. Use the main domain. - A name must match the whole company name. Case, accents, punctuation and common trailing legal suffixes are ignored, so
FedEx Corporation,fedexandFedEx, Inc.find the same companies. - It is not a partial match:
Glenmarkdoesn’t findGlenmark Pharmaceuticals, andFidelityfinds the company called Fidelity, not everyFidelity*employer.
For example, FedEx is indexed on Workday, so FedEx with
sources: ["greenhouse"] returns companies_outside_sources and no jobs, however you spell the name. To find a stored spelling, search the name as free text and read company.name: q=Glenmark surfaces jobs at Glenmark Pharmaceuticals.
Filter by occupation
occupation in a three-level taxonomy, such as Healthcare › Nursing › Registered Nurse. Filter on any level:
The free
GET /api/occupations lists every value. Cache it and refetch now and then: its version changes when occupations or the hierarchy change, but display names can improve without a new version.
On POST you can also exclude. Every nursing job except registered nurse roles:
- Matching is exact but ignores case:
healthcareworks,Health carematches nothing. - Filter occupations by id, never by name. Names can improve between taxonomy releases; ids don’t.
- A job without an
occupationnever matches anincludelist. qandqueriesdon’t search occupation names. To find every job of one occupation, whatever the employer called it, useoccupation_ids.- With a sandbox key,
POST /api/jobs/searchignores these filters (with anunknown_request_fieldswarning) and returns no occupation facets. Test them with a live key.
Open-ended salary range
Posted window vs discovered window
To page through a discovered window without jobs shifting between pages, add
"sort": "discovered_asc". See Stable pages over a fixed window.
Everything at once
Iterate every match
iter_jobs pages through the results for you.
Shrinking the response
description dominates payload size; dropping it is the biggest saving for high-volume search. include_fields keeps only the non-core fields you name. Core fields (id, title, company, locations, compensation, dates, source, flags) always come back.
- The five omittable fields are
description,summary,qualifications,responsibilitiesandbenefits. Unknown names are dropped. - On
GET, pass a comma-separated string (?include_fields=description,benefits), or?include_fields=for core fields only. - A non-core field you didn’t request is still present but empty:
descriptionis"",summaryisnull, and the list fields are[].
Facets
facets holds server-computed counts, keyed by canonical value.
key goes straight back in as a filter value; the display values on a job don’t (see Enums). countries keys are lowercased country names (united states): pass them back as locations. company_categories keys go into the company_categories include/exclude filter.
Occupation facets
job_categories and job_subcategories keys are lowercased names (healthcare, nursing); occupations keys are occupation ids. Each goes back into the filter of the same name (occupations into occupation_ids). Only these buckets carry two extra fields:
"include_facets": ["job_categories", "job_subcategories", "occupations"]) and nest them by parent to build a category › subcategory › occupation filter tree from one response.
Facet limits
- Unknown facet names are silently dropped. If
include_facetsholds only unknown names (say, the typowork_models), you get no facets, not the defaults. - Each facet returns at most 8 buckets, with approximate counts. Take exact totals from
total, not from summed facet counts. - With that cap, a subcategory’s parent may be missing from the category buckets. Use
GET /api/occupationsfor the full tree. - A facet with no buckets is left out of
facets, not returned as an empty array.
Building this with an AI coding assistant?
Copy-paste prompts that hand your assistant the full search contract: add job search to your app, or audit an existing integration for silent failures.

