Career Site Jobs API: Greenhouse, Lever, Workday, Ashby ATS avatar

Career Site Jobs API: Greenhouse, Lever, Workday, Ashby ATS

Pricing

from $1.40 / 1,000 job rows

Go to Apify Store
Career Site Jobs API: Greenhouse, Lever, Workday, Ashby ATS

Career Site Jobs API: Greenhouse, Lever, Workday, Ashby ATS

Every open job from 18,120 company career sites, or any Greenhouse, Lever, Workday, Ashby or 8 more ATS boards you list. Seniority, skills, visa sponsorship and salary on every row. New, changed and removed jobs on a schedule. Pay per job.

Pricing

from $1.40 / 1,000 job rows

Rating

0.0

(0)

Developer

Navista Multani

Navista Multani

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

4 minutes ago

Last modified

Share

A job postings API for company career sites: get every open job straight from the applicant tracking systems companies post on (Greenhouse, Lever, Workday, Ashby and 10 more) in one clean format. Search 33,310 company boards by job title and location, or list the companies you want, and track new, changed and removed jobs on a schedule.

Job postings API: what you can use it for

  • Build a job board, newsletter or job alert. One schedule fills your site with fresh jobs straight from employers, already in one format, with the employer's own apply link.
  • Monitor company careers pages. List the companies you follow (competitors, customers, portfolio companies) and get only new, changed and removed jobs each day.
  • Find jobs with visa sponsorship, a salary range or a seniority level. Every row carries visa_sponsorship, salary, seniority, experience_years_min and skills, so you filter on them instead of reading descriptions.
  • Study the job market. Who is hiring for what, where, at what pay and with which skills, in columns ready for a spreadsheet or a database.
  • Give an AI agent live job data. Every row stands alone, so it drops into an LLM's context or a RAG index without joins; call it through the Apify API or MCP server.

Job data API: sample output

One row per job, the same fields on all 14 platforms. A real row (Sonos on Workday, recorded 2026-10-24; description shortened):

{
"id": "workday:sonos/sonos:Senior-Salesforce-Engineer_R2847",
"source": "workday",
"board": "sonos/Sonos",
"company": "Sonos, Inc.",
"title": "Senior Salesforce Engineer",
"department": null,
"team": null,
"category": null,
"employment_type": "full_time",
"workplace_type": null,
"location": "Boston, MA",
"locations": ["Boston, MA"],
"country": "United States of America",
"salary": { "min": 165000, "max": 206000, "currency": "USD", "period": "year", "source": "description_text" },
"salary_text": null,
"seniority": "senior",
"experience_years_min": 8,
"visa_sponsorship": false,
"skills": ["AWS", "CI/CD", "Git", "Test automation", "Salesforce", "CRM"],
"posted_at": "2026-10-09T00:00:00Z",
"updated_at": null,
"url": "https://sonos.wd1.myworkdayjobs.com/Sonos/job/Boston-MA/Senior-Salesforce-Engineer_R2847",
"apply_url": "https://sonos.wd1.myworkdayjobs.com/Sonos/job/Boston-MA/Senior-Salesforce-Engineer_R2847",
"description_text": "At Sonos we want to create the ultimate listening experience for our customers ...",
"content_hash": "bffcfc146e91ec6f",
"scraped_at": "2026-10-27T15:07:13Z"
}

What each row holds:

  • Job: title, company, department, team, category, employment_type, url, apply_url, posted_at, updated_at
  • Place: location, locations (all of them), country, workplace_type (remote, hybrid, onsite)
  • Pay: salary as {min, max, currency, period, source} (ISO currency, period year/month/week/day/hour), plus salary_text where the board shows a label
  • Read from the posting by fixed rules, on every row:
    • seniority: intern, entry, mid, senior, lead, manager, director or executive, from the title
    • experience_years_min: the years of experience the description asks for ("5+ years" gives 5)
    • visa_sponsorship: true if the posting says it sponsors visas, false if it says it does not, null if it says neither
    • skills: tools and skills named in the posting (Python, AWS, Salesforce, SQL, Figma and about 480 more)
  • Text: description_text (plain text), optionally description_html
  • Tracking: stable id, source (the platform), board, content_hash, scraped_at, and in change mode change (new, changed, removed) and removed_at

Notes:

  • salary.source: structured (the platform's salary fields), pay_range_html (the employer's pay-range block on Greenhouse), label_text or description_text (a pay range stated in text). currency is null when the text gives only $ and the job is not only in the US; period is null when the source does not make it clear.
  • company: Lever, Ashby and Gem feeds carry no company name, so it is read from the board's public page title (for example "Spotify"), else taken from the directory, else made from the board name. Pinpoint feeds have none either; there company is empty and board names the company.
  • Pinpoint feeds have no posting date, so postedWithinDays drops Pinpoint jobs.
  • workplace_type comes from the platform's own field where it has one, otherwise only remote or hybrid read from the location; it is never guessed as on-site.
  • The OUTPUT record summarizes the run: boards loaded, not found or failed, jobs found and returned. A board that does not exist does not fail the run; a run where no board loads does.
  • The dataset has three views: Jobs, Seniority, skills and visa, and Changes.

Career site jobs from 14 ATS platforms: how it compares

  • A full live snapshot of each board, not a time window. Each run reads the board's whole current job list, so you get every open job, not only jobs first seen in the last day or week.
  • Expired jobs included at no extra cost. In change mode, jobs taken down since your last run come back as removed rows. You do not need a separate expired-jobs tool.
  • Direct employer postings. Every row comes from the company's own career site, not from a job board's repost, so there are no duplicates from aggregators and the apply link is the employer's.
  • Seniority, years, visa and skills without an AI model. The four fields are read by fixed, published word rules, so the same posting always gives the same answer, and a field stays empty rather than guessed. Hand-checked on 30 recorded postings (2026-10-27): no wrong seniority, years or visa value, and 126 of 130 skills correct; see the FAQ for what the rules miss.
  • Complete rows on every run. No start fee, no per-run charge, no paid tier for the extra fields: every row has every field the source provides.
  • Large Workday boards in full. Workday shows at most 2,000 jobs per search; larger boards are split automatically, so a 14,000-job board comes back complete.

What it is not: it does not cover hundreds of thousands of sites, and it does not add company data from other sources (headcount, funding, social profiles).

Scrape job postings: ready-made examples

Open one, press Start, and change the input to suit you:

Jobs with visa sponsorship

{
"keywords": ["engineer"],
"visaSponsorship": true,
"maxJobs": 100
}

Only postings that say they sponsor visas are kept; most postings say nothing either way, so expect a small share of all jobs. To narrow by country, add locations (for example United States, USA, United Kingdom, Canada, Germany). A location matches when the job's location or country text contains it, and platforms write countries differently, so list the usual spellings and the main cities.

Pricing

Pay per job row returned, from $2.00 per 1,000 jobs. No start fee and no charge for jobs your filters drop. A removed-job row in change mode counts as one row. The run stops cleanly at your spending limit.

  • Test run, 20 jobs: $0.04.
  • Directory search for "data engineer" in Berlin and remote, 200 jobs: $0.40.
  • Monitoring 25 company boards daily: a first full run of about 2,500 jobs costs $5.00; after that a daily change-mode run with about 50 new, changed or removed jobs costs about $0.10, about $3 a month.

Job listing API input: examples and settings

Search the directory by title and location

{
"keywords": ["data engineer", "analytics engineer"],
"locations": ["Berlin", "Remote"],
"seniority": ["senior", "lead"],
"postedWithinDays": 14,
"maxJobs": 200
}

With no boards, the run searches the directory live, starting with the boards most likely to match (those whose titles and locations contained your words when the directory was built, largest first). It stops at maxJobs matches (500 when maxJobs is 0) or when searchTimeLimitSecs (default 150) runs out. At the time limit, boards still being read are cut off and the jobs from boards already read are returned, so the run ends close to the limit; its status says how many boards it searched and how many were cut off. Measured on Apify 2026-10-25: "data engineer" with maxJobs 100 returned 100 jobs from 69 boards in 30 seconds.

Read the companies you choose, in full

{
"boards": [
"https://job-boards.greenhouse.io/dropbox",
"https://jobs.lever.co/spotify",
"https://jobs.ashbyhq.com/posthog",
"https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
"greenhouse:stripe"
],
"workplaceTypes": ["remote"],
"requireSalary": true
}

All input fields

FieldWhat it does
keywordsTitle words to look for (any of them). Without boards, these are the directory search.
locationsKeep jobs whose location or country contains any of these, for example London, Remote, United States.
maxJobsStop after this many jobs, newest first. 0: no limit with boards, 500 for a directory search.
workplaceTypesremote, hybrid, onsite. Jobs whose board does not say are dropped while this is set.
seniorityKeep these levels: intern, entry, mid, senior, lead, manager, director, executive. Titles with no level are dropped while this is set.
postedWithinDaysKeep jobs first published within this many days.
visaSponsorshipKeep only jobs whose posting says it sponsors visas.
requireSalaryKeep only jobs that publish pay.
keywordsInDescriptionAlso match keywords in descriptions. Broader, noisier, and slower on Rippling and Workday.
boardsCareer-site URLs or short forms (see Supported ATS platforms). Empty: search the directory.
onlyChanges / stateNameChange mode (see below), and an optional name for a separate change history.
includeDescription / includeHtmlPlain-text description (on by default) and original HTML (off).
maxJobsPerBoardAt most this many jobs per board, newest first.
searchSources / searchMaxBoards / searchTimeLimitSecsDirectory search only: which platforms, how many boards (largest first), and the time limit.
minRowsFail the run when it returns fewer rows than this, so a scheduled run that comes back short triggers your alerts.

Track new, changed and removed jobs on a schedule

Turn on onlyChanges and run the same input on a schedule. The first run returns every job as change: "new" and remembers them; each later run returns only:

  • new: jobs that appeared since the last run,
  • changed: jobs whose title, team, location, workplace type, salary, description or apply link changed,
  • removed: jobs that are gone (filled or taken down), as {"id", "source", "board", "change": "removed", "removed_at"}.

A board that fails to load is skipped for that run; its jobs are not reported as removed.

Example: monitor three companies every morning.

  1. Save this input as a task:

    {
    "boards": ["greenhouse:stripe", "lever:spotify", "ashby:posthog"],
    "onlyChanges": true,
    "minRows": 0
    }
  2. In Apify Console, create a schedule (for example daily at 07:00, cron 0 7 * * *) and add the task to it.

  3. Read each run's dataset, or connect a webhook or integration to send the rows on.

The change history is kept per input (boards plus filters). Use stateName to keep two separate histories for the same input.

Supported ATS platforms and board URLs

PlatformPaste a URL likeShort form
Workdayhttps://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite, https://wd1.myworkdaysite.com/recruiting/wf/WellsFargoJobsworkday:nvidia.wd5/NVIDIAExternalCareerSite
Greenhousehttps://job-boards.greenhouse.io/stripe (EU boards too)greenhouse:stripe
Leverhttps://jobs.lever.co/spotify (EU boards too)lever:spotify
Ashbyhttps://jobs.ashbyhq.com/posthogashby:posthog
Recruiteehttps://bunq.recruitee.comrecruitee:bunq
Personiohttps://tado.jobs.personio.depersonio:tado
Teamtailorhttps://tibber.teamtailor.comteamtailor:tibber
Workablehttps://apply.workable.com/huggingfaceworkable:huggingface
Ripplinghttps://ats.rippling.com/aalyria-careers/jobsrippling:aalyria-careers
JazzHRhttps://snapsheet.applytojob.comjazzhr:snapsheet
Gemhttps://jobs.gem.com/gemgem:gem
Pinpointhttps://safetywing.pinpointhq.compinpoint:safetywing
Joinhttps://join.com/companies/joinjoin:join
Paylocityhttps://recruiting.paylocity.com/Recruiting/Jobs/All/015e2e4d-77b3-437f-92d5-dc5b62d176d5paylocity:015e2e4d-77b3-437f-92d5-dc5b62d176d5

All but Workday are in the searchable directory; Workday boards are read when you list them. Any page of a board works, even a single job's page (Paylocity: use the company's job list, since its job pages do not name the company). Boards on a company's own domain (for example careers.example.com served by one of these platforms) are not recognized; use the platform URL.

FAQ

Is there a free job postings API, and how is this different? Several platforms publish a free public feed per company: Greenhouse's Job Board API, Lever's Postings API and Ashby's job board API each return one company's open jobs, in that platform's own format. This Actor reads those feeds (and the career-site data of 11 more platforms), so you get a search across many companies by title and location, one row format for all 14 platforms, the seniority, years, visa and skills fields, and change tracking, without knowing each company's board in advance.

How do I scrape job postings from a company's career site? Open the careers page, click any job, and copy the address if it is on one of the platforms above (job-boards.greenhouse.io, jobs.lever.co, myworkdayjobs.com and so on). Paste it into boards; any page of the board works.

How fresh is the directory? It lists the boards found in Common Crawl's public web index, JazzHR's and Join's public sitemaps and public job lists on GitHub, each checked to have open jobs when it was built (2026-10-28; about 531,000 open jobs then). The jobs themselves are always read live. Companies not in it can be read by listing their board.

Does a directory search read every board? It reads boards until it has maxJobs matches or reaches its time limit, likeliest boards first. A rare title may not reach every board within the limit; raise searchTimeLimitSecs, narrow searchSources, or list boards. In change mode a search does not stop at maxJobs (it still stops at its time limit, and boards it did not reach or cut off never count as removed). Boards with 1,000 or more open jobs are searched only on Greenhouse; list the others (about 21 boards, mostly recruiting agencies).

How do I find jobs with visa sponsorship in the USA, UK or Canada? Turn on visaSponsorship and add the country to locations (see Jobs with visa sponsorship above). Only postings that state sponsorship are returned; a posting that says nothing is not counted as sponsoring.

How are seniority, years, visa and skills decided?

  • seniority comes from title words only: "Senior", "Sr." give senior; "Staff", "Principal", "Lead" give lead; "Engineering Manager", "Manager, Marketing" give manager, but "Product Manager" or "Account Manager" stay empty because they are not people-management titles; "Head of" and "Director" give director; "VP" and "Chief ... Officer" give executive. A title without such a word stays empty.
  • experience_years_min is the first number of years the description ties to experience; "10 years ago" or "a 4-year degree" never count.
  • visa_sponsorship is set only by a sentence that ties sponsorship to a visa or work authorization; "executive sponsor" or sponsoring events never count, and a posting that says both yes and no gives null.
  • skills match whole words from a fixed list of 486 tools and skills; short names that are also ordinary words (Go, R, C, Spark, Excel) count only in their usual form or in a list of tools. A skill named like the employer is left out (a Datadog posting does not list Datadog). A skill mentioned in the employer's own description of itself still counts.
  • The rules read English best; German postings get seniority (Werkstudent, Praktikant, Junior, Senior) and years ("3 Jahre Berufserfahrung").

Why is a filtered run slower on some platforms? Workday, Rippling, JazzHR, Join and Paylocity need one request per job for the description, date or pay. Title keywords, seniority, postedWithinDays and maxJobsPerBoard are applied before those requests; visaSponsorship and requireSalary need the full posting, so they are applied after.

Can I use it from Python or an AI agent? Yes, through the Apify API (with the official Python or JavaScript client), the Apify MCP server, or any Apify integration such as Make, Zapier or n8n.

Does it return personal data? No. Email addresses and phone numbers are removed from descriptions, and recruiter or hiring-manager names are never returned.

Why is SmartRecruiters missing? Its API's robots.txt disallows automated access, so SmartRecruiters URLs are reported as invalid boards.

Data sources and terms

Every job is read from the public job feed or career-site API that the platform publishes for the company's own careers page, the same postings anyone can see there. No login, no browser and no proxy are used, and nothing is read that the board does not show publicly. Platforms whose robots.txt disallows the paths needed (SmartRecruiters) are not supported. Job postings belong to the employers; use the data in line with your own obligations, for example when you republish it.