API Access
Every field tagged with the source it came from, and every gap in the data published before you pay — including the ones that make us look bad. Collected employer-direct from applicant-tracking systems, employers' own careers pages and public agencies. 3,314,163 live openings across 178,393 employers.
GET https://api.jobopportunitiesapi.org/public/jobs?country=FR&require_fields=description&limit=5GET https://api.jobopportunitiesapi.org/v1/jobsGET https://api.jobopportunitiesapi.org/v1/companiesGET https://api.jobopportunitiesapi.org/v1/changes?since=2026-07-01T00:00:00ZGET https://api.jobopportunitiesapi.org/v1/jobs/closed?closed_after=2026-07-01GET https://api.jobopportunitiesapi.org/v1/meta/freshnessGET https://api.jobopportunitiesapi.org/public/providersGET https://api.jobopportunitiesapi.org/public/freshnesshttps://jobopportunitiesapi.org/compare — including where a rival winsGET https://api.jobopportunitiesapi.org/v1/openapi.yamlAuthorization: Bearer YOUR_API_SECRET?category=Engineering&country=DE?remote_confirmed=true&has_description=true&has_salary=true?require_fields=salary,descriptionone page per filter, up to 50 rows, ~2 req/spaging, 1,000 records a month, no card?source_type=ats,career_site,public_agency?provider=greenhouse,lever?exclude_provider=company_site?title=platform+engineer&title_exclude=intern?description_contains=kubernetes?include_description=true&limit=50?company_domain=stripe.com,figma.com?min_salary=60000&max_salary=120000GET /v1/jobs/expired?since=2026-08-01T00:00:00Z?exclude_category=Sales&exclude_country=US{
"data": [
{
"id": "8f2c…", "slug": "backend-engineer-8f2c1a4b",
"title": "Backend Engineer", "company": "Nordbridge Labs",
"company_slug": "nordbridge-labs",
"category": "Engineering", "category_confidence": 0.82,
"country": "DE", "city": "Berlin",
"remote": "hybrid", "remote_inferred": false,
"employment_type": "Full-time", "seniority": "Senior",
"posted_at": "2026-07-12T09:00:00Z",
"last_verified_at": "2026-08-03T04:00:00Z",
"status": "live", "closed_at": null, "closed_reason": null,
"source": "greenhouse",
"source_type": "ats", "provider_type": "employer_ats",
"has_description": true,
"field_sources": {
"remote": "published", "employment_type": "published",
"category": "inferred", "seniority": "inferred",
"salary": "absent", "location": "published",
"posted_at": "published", "description": "published",
"source_type": "inferred"
}
}
],
"next_cursor": "2026-07-12T09:00:00.481Z|8f2c…",
"has_more": true
}field_sources marks each field published (carried by the source), inferred (derived by us) or absent. 89% of the ledger has a remote status we worked out from the listing text rather than one the employer stated — ?remote_confirmed=true narrows to the stated ones. category and seniority are always inferred: they are read off the job title, and category_confidence says how sure.last_verified_at is a re-confirmation at the source, not a posting date. Filter with ?verified_after=, and see the coverage for yourself at /v1/meta/freshness./v1/jobs/closed returns roles that have come off their source, with closed_at and a closed_reason — expired_upstream when we proved the vacancy dead, not_seen when it simply stopped appearing. A req that opened and closed in nine days is a hiring signal, not a dead link.source_type is ats, career_site or public_agency on every row, and provider names the exact system underneath — so ?provider=greenhouse,lever is a query parameter, not a post-filter you write yourself.?q= covers title, company and location. ?title= covers the title alone, ?description_contains= the advert body — because “engineer in the title” and “engineer mentioned somewhere” are different questions and one box cannot answer both without choosing for you. They combine as an AND. Ask for the body text itself with ?include_description=true.salary_min_annual_eur is one number in one unit, so ?min_salary=60000 means something — and it is null, never a guess, when the period or currency is unknown. Only 6.1% of the ledger publishes structured salary, so this is a narrow filter; the rates and the hours-per-year we assumed are printed in /v1/meta/freshness so you can check our arithmetic.field_sources object, the rate-limit headers and all three of this API’s cursors./public/ is a real, bounded mirror of the same rows, capped at one page per filter and 50 rows.Explore
Every REST endpoint, against the live ledger — the same rows the paid tiers return. No card, no expiry.
- 1,000 records / month
- No delta feed
- REST only, no bulk export
Growth
For one product: a job board, a dashboard, a research project.
- 60,000 records / month
- Delta feed for incremental sync
- REST only, no bulk export
Signal
Hiring signal at scale, or one country with no record limit.
- 400,000 records / month
- Delta feed for incremental sync
- Bulk export of the full corpus
- …or one country with no record limit
Scale
Full-corpus refreshes, bulk export and the closure feed.
- 2,000,000 records / month
- Delta feed for incremental sync
- Bulk export of the full corpus
Free access for students, nonprofits and research
Tell us what you are building and why. We grant free, time-limited keys by hand.
Email us your use caseEvery listing carries its provenance and you can filter on it: an employer’s ATS, the company’s own careers page, or a public employment agency. There is no aggregator inventory here at all — those sources are not redistributable, so they never enter the ledger and every row you get is first-party. The aggregator and agency filter values are accepted for forward compatibility, but today they match nothing.