ATS Hiring Monitor: Greenhouse, Lever, Ashby, SmartRecruiters avatar

ATS Hiring Monitor: Greenhouse, Lever, Ashby, SmartRecruiters

Pricing

from $1.00 / 1,000 job postings

Go to Apify Store
ATS Hiring Monitor: Greenhouse, Lever, Ashby, SmartRecruiters

ATS Hiring Monitor: Greenhouse, Lever, Ashby, SmartRecruiters

Watch a list of companies' job boards. Auto-detects Greenhouse, Lever, Ashby or SmartRecruiters, returns normalised job postings, and in incremental mode outputs only roles that are new, changed or removed since the last run.

Pricing

from $1.00 / 1,000 job postings

Rating

0.0

(0)

Developer

James Bailey

James Bailey

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

2 days ago

Last modified

Share

ATS Hiring Monitor: Greenhouse, Lever, Ashby & SmartRecruiters

Give it a watchlist of companies. It finds each company's job board, pulls every open role into one clean format, and on later runs tells you only what's new, what changed and what was taken down since last time.

Use it to:

  • Track hiring signals for sales and investment research: which target accounts just opened a sales, security or data team, or quietly pulled a batch of roles.
  • Job hunt without refreshing 30 careers pages: schedule it daily with a title filter like engineer and get only fresh postings.
  • Feed a jobs board, newsletter or spreadsheet with normalised postings from many companies at once.

Everything comes from the ATS providers' official public job-board APIs (the same feeds companies use to embed jobs on their own sites). No logins, no browser, no proxies, and no candidate or recruiter personal data.

Supported ATS providers

ProviderDetected fromNotes
Greenhouseboards.greenhouse.io/<token>, job-boards.greenhouse.io/<token>, embed scriptsCompany name, department, first-published and last-updated dates
Leverjobs.lever.co/<slug> (global and EU hosting)Team, department, commitment, workplace type, salary range when published
Ashbyjobs.ashbyhq.com/<name>Team, department, workplace type, published compensation
SmartRecruitersjobs.smartrecruiters.com/<Company>, careers.smartrecruiters.com/<Company>Company name, function, employment type, remote/hybrid flags

Workday, Workable, Recruitee, Teamtailor, Personio and BambooHR are planned.

How company detection works

For each line in Companies the Actor:

  1. Uses it directly if it's a job-board URL (https://jobs.lever.co/spotify) or an explicit pair (greenhouse:stripe).
  2. Otherwise turns the name or domain into likely board IDs (Rocket Lab → rocketlab, rocket-lab; stripe.com → stripe) and checks all four providers.
  3. For domains, if that fails, reads the company's own /careers, /jobs and home page looking for links to a supported ATS (this is how octopus.energy resolves to Lever board octoenergy).

If a company turns up on more than one provider (common after an ATS migration), the board with the most live postings wins and the others are listed under alsoFoundOn in the run summary. For a watchlist you care about, paste the board URL or ats:board pair: it's exact, and skips detection requests.

Input

FieldTypeDefaultDescription
companiesarray of strings(required)Company names, domains, job-board URLs or ats:board pairs, one per line
modeincremental / fullfullFull outputs every live posting. Incremental outputs only new, changed and removed postings (a repeat run with no changes returns nothing)
titleKeywordsarray of strings[]Only output postings whose title contains any of these (case-insensitive)
locationKeywordsarray of strings[]Only output postings whose location or workplace type contains any of these, e.g. london, remote
includeDescriptionbooleanfalseAdd plain-text job descriptions (Greenhouse, Lever, Ashby)
stateStoreNamestringats-hiring-monitor-stateNamed key-value store that remembers postings between runs. Use one per independent watchlist
maxConcurrencyinteger5Companies fetched in parallel

Example input

{
"companies": [
"stripe.com",
"https://jobs.lever.co/spotify",
"ashby:ramp",
"CERN",
"Rocket Lab"
],
"mode": "incremental",
"titleKeywords": ["engineer", "analyst"],
"locationKeywords": ["london", "remote"]
}

Incremental mode

The Actor keeps a snapshot of every board it has seen in a named key-value store (stateStoreName), so it survives between runs. Each run compares live postings with that snapshot:

  • new: a posting that wasn't there last run
  • changed: same posting ID, but the title, location(s), department, team, employment type, workplace type, compensation or URL changed. changedFields lists each change with its previous and current value
  • removed: was there last run and is gone now (closed, filled or unpublished)
  • unchanged: only output in full mode

Details worth knowing:

  • The first run for a board has nothing to compare against, so everything is new.
  • Last-updated timestamps and description edits are deliberately ignored, because ATSs bump them for invisible admin edits and they'd bury the real changes.
  • If a board can't be fetched in a run (API down, typo), its saved state is left alone, so you never get a false wave of "removed" followed by "new".
  • Keyword filters only affect what's output, not what's tracked, so you can change filters between runs without corrupting the history.
  • Schedule the Actor (daily is typical) with the same stateStoreName to get a clean change feed. Different watchlists should use different store names.

Output

One dataset item per posting. Example (incremental run, a role that moved from hybrid to remote):

{
"changeType": "changed",
"ats": "lever",
"boardId": "spotify",
"jobId": "2193db3f-77c5-43b8-b030-8f92c9882bf1",
"company": "Spotify",
"title": "Android Engineer - Experience",
"location": "London",
"locations": ["London", "Stockholm"],
"department": "Engineering",
"team": "Experience",
"employmentType": "full-time",
"workplaceType": "remote",
"compensation": null,
"url": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1",
"applyUrl": "https://jobs.lever.co/spotify/2193db3f-77c5-43b8-b030-8f92c9882bf1/apply",
"postedAt": "2026-06-23T11:29:45.805Z",
"updatedAt": null,
"description": null,
"changedFields": [
{ "field": "workplaceType", "previous": "hybrid", "current": "remote" }
],
"firstSeenAt": "2026-09-21T06:00:04.112Z",
"removedAt": null,
"input": "https://jobs.lever.co/spotify",
"detectedVia": "explicit",
"scrapedAt": "2026-09-28T06:00:03.871Z"
}
FieldNotes
changeTypenew, changed, unchanged (full mode only) or removed
ats, boardId, jobIdTogether these uniquely identify a posting
companyFrom the ATS where it provides one (Greenhouse, SmartRecruiters), otherwise from your input
location, locationsPrimary location plus every listed location
employmentTypeNormalised to full-time, part-time, contract, internship, temporary where recognisable
workplaceTyperemote, hybrid, onsite or null when the ATS doesn't say
compensationSalary text where the company publishes it (mostly Ashby and Lever)
postedAt, updatedAtISO 8601. updatedAt is only available from Greenhouse
firstSeenAt, removedAtWhen this Actor first saw the posting, and when it noticed it gone
detectedViaexplicit, slug-guess or careers-page:<url>, so you can audit detection

Fields a provider doesn't expose are null rather than missing, so every item has the same shape.

The run's OUTPUT record (default key-value store) has a per-company summary: which board was detected, how many live postings, counts of new/changed/removed, and any company that couldn't be matched (not_found) or errored.

Pricing

Pay per event: $0.001 per job posting delivered to your dataset, plus $0.01 per run. In incremental mode you only pay for postings that are new, changed or removed, which is usually a small fraction of a board, so daily monitoring of a large watchlist stays cheap. A run where nothing changed costs just the $0.01 start fee.

Limitations

  • Only the four providers above for now. Companies on Workday, Workable and others come back as not_found.
  • Auto-detection can match a different company that happens to use the same board slug. Check detectedVia and alsoFoundOn in the run summary, and pin exact board URLs for anything important.
  • Careers-page detection only sees links present in the page's HTML; job widgets that load entirely from JavaScript won't be found. Paste the board URL instead.
  • SmartRecruiters descriptions aren't included yet (they need one extra request per posting).
  • Boards are capped at 10,000 postings for SmartRecruiters.

The Actor reads each ATS provider's public job-board API, which exists so that job postings can be displayed and shared. It doesn't log in, bypass any access control, or collect personal data. You're still responsible for how you use the results, particularly if you republish them.

Support

Found a bug or a company that won't resolve? Open an issue on this Actor's Issues tab with the company name and what you expected.