Skip to main content
POST
cURL

Authorizations

X-Api-Key
string
header
required

Your Jobo API key. Create one in the dashboard under Developers → API Keys. Live keys start with jbe_live_ and sandbox keys with jbe_test_.

Body

application/json

Cursor-paginated feed request. The cursor keeps the first request's filters, stable_scan ordering and batch_size: filters sent with a cursor are ignored, and batch_size can be lowered but never raised. description_format is read from every request. Start a new scan to change the filters.

locations
object[] | null

Structured location filters. A job matches if it matches ANY entry. Each entry routes to its most-specific populated level (city, then region, then country) and every level needs country. Use {"country": "Remote"} to match remote jobs.

sources
string[] | null

Restrict to these ATS provider ids (e.g. greenhouse, lever, workday). See Sources for every id.

work_models
enum<string>[] | null

Filter by work model: remote, hybrid, onsite. null = all jobs

Available options:
remote,
hybrid,
onsite
employment_types
enum<string>[] | null

Filter by employment type. null = all jobs

Available options:
full-time,
part-time,
contract,
internship,
freelance,
temporary
experience_levels
enum<string>[] | null

Filter by experience level. null = all jobs

Available options:
intern,
entry,
mid,
senior,
lead,
executive
languages
string[] | null

Filter by description language, as ISO 639-1 codes (en, de, fr). Language names and locales (English, en-US) are mapped to their code. null = all jobs.

exclude_sources
string[] | null

Leave out jobs from these ATS provider IDs (e.g. lever, workday), normalized like sources. May be combined with sources: sources: [greenhouse, lever] with exclude_sources: [lever] returns Greenhouse jobs.

exclude_work_models
enum<string>[] | null

Leave out jobs with these work models. Jobs whose work model is unknown are kept.

Available options:
remote,
hybrid,
onsite
exclude_employment_types
enum<string>[] | null

Leave out jobs with these employment types. Jobs whose employment type is unknown are kept.

Available options:
full-time,
part-time,
contract,
internship,
freelance,
temporary
exclude_experience_levels
enum<string>[] | null

Leave out jobs at these experience levels. Jobs whose experience level is unknown are kept.

Available options:
intern,
entry,
mid,
senior,
lead,
executive
exclude_languages
string[] | null

Leave out jobs whose description is in these languages, as ISO 639-1 codes; names and locales are mapped as for languages. Jobs whose language is unknown are kept.

companies
object | null

Include/exclude companies, matched as on POST /api/jobs/search. Each entry is a Jobo company ID, a website domain or URL (fedex.com), or a whole company name (FedEx), case-insensitive and never a partial match.

Entries are matched once, on the first page; the cursor keeps the matched company IDs. An entry that matches nothing is not a 400: the first page's warnings lists companies_unmatched (include), companies_exclude_unmatched (exclude) or companies_outside_sources (matches on none of the requested sources). If the include list matches no company, or none on the requested sources, the first page has jobs: [], has_more: false, next_cursor: null and estimated_total: 0, and is not billed.

job_categories
object | null

Include/exclude filter on the job's occupation category (occupation.category, e.g. Healthcare). Exact, case-insensitive match. GET /api/occupations lists every value. Jobs without an occupation never match an include list.

job_subcategories
object | null

Include/exclude filter on the job's occupation subcategory (occupation.subcategory, e.g. Nursing). Exact, case-insensitive match. GET /api/occupations lists every value.

occupation_ids
object | null

Include/exclude filter on occupation id (occupation.id, e.g. esco:8d3e8aaa-791b-4c75-a465-f3f827028f50). Use ids, not names: names can improve between taxonomy releases, ids don't. GET /api/occupations lists every id.

industries
object | null

Include/exclude filter on the hiring company's industries (company.industries, e.g. Software Development), matched on the whole name, case-insensitively. Include keeps jobs whose company has ANY of the values; exclude drops jobs whose company has any of them.

company_primary_industries
object | null

Include/exclude filter on the company's single primary industry (primary_industry on the company profile, GET /api/companies/{id}, e.g. Finance). Exact, case-insensitive match.

company_categories
object | null

Include/exclude filter on the hiring company's business model (categories on the company profile, GET /api/companies/{id}), case-insensitive: b2b, b2c, b2b2c, saas, marketplace, service-provider. Include keeps jobs whose company has ANY of them; exclude drops jobs whose company has any of them.

company_sizes
object | null

Include/exclude filter on the company's headcount band (company_size on the company profile, GET /api/companies/{id}). Companies of unknown size never match an include list and are kept by an exclude list. An unknown band is a 400.

company_revenues
object | null

Include/exclude filter on the company's annual revenue band (revenue on the company profile, GET /api/companies/{id}). Companies of unknown revenue never match an include list and are kept by an exclude list. An unknown band is a 400.

company_is_agency
boolean | null

false leaves out jobs that recruitment and staffing agencies post on behalf of other employers (is_agency on the company profile, GET /api/companies/{id}); true returns only theirs. Omit or null = all jobs.

posted_after
string<date-time> | null

Return jobs whose employer posting time or first-indexed time is on or after this UTC timestamp. Use updated_after when edits matter.

include_reactivated
boolean
default:false

Also return jobs that expired and were reactivated (rediscovered and re-indexed) on or after posted_after. A reactivated job keeps its original posting and creation dates, so posted_after alone never re-delivers it.

No effect without posted_after. An updated_after sync doesn't need it: updated_after already returns reactivated jobs. With both timestamps set, a job must match both.

description_format
enum<string>
default:markdown

Format of each job's description. markdown (default) returns it as stored. html renders it to HTML on the fly: raw HTML in the source is escaped and only http(s), mailto and relative URLs are kept. Read from every request, including cursor continuations.

Available options:
markdown,
html
updated_after
string<date-time> | null

Return jobs created, updated or re-indexed on or after this UTC timestamp, including jobs reactivated in that window. The watermark for incremental syncs: see Sync a database.

stable_scan
boolean
default:true

true (default) pages by creation time, so jobs updated or deleted mid-scan are never skipped or duplicated. false is the legacy update-recency order: its scans stop at 1,000,000 results with 409 feed_cursor_restart_required.

cursor
string | null

Opaque cursor from next_cursor. Omit on the first request.

batch_size
integer
default:1000
Required range: 1 <= x <= 1000

Response

Batch of jobs with cursor for next page

jobs
object[]
required
next_cursor
string | null
required
has_more
boolean
required
estimated_total
integer<int64> | null

Estimated number of jobs the scan will deliver. Present on the first page of a scan only; null on continuation pages. Exact when 1,000 or fewer jobs match; above that an estimate that can run a few percent high.

warnings
object[] | null

POST /api/jobs/feed only: non-fatal problems with the first page's request, e.g. a companies entry that matched no company (companies_unmatched, companies_exclude_unmatched, companies_outside_sources). Present on the first page only, and only when there is something to report. The same codes are on the X-Jobo-Warnings response header, comma-separated.