Career Site Jobs Monitor - Greenhouse, Lever, Ashby & more
Pricing
$1.00 / 1,000 job posting scrapeds
Career Site Jobs Monitor - Greenhouse, Lever, Ashby & more
Live job postings from career sites on Greenhouse, Lever, Ashby, Workable and SmartRecruiters via their public JSON APIs. No login, no proxies. Paste a careers URL and the ATS is auto-detected. Stable dedup keys, ISO dates and keyword/location/date filters for new-roles-since-last-run monitoring.
Pricing
$1.00 / 1,000 job posting scrapeds
Rating
0.0
(0)
Developer
Imran
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Career Site Jobs Monitor — Greenhouse, Lever, Ashby, Workable, SmartRecruiters
Pull live job postings straight from company career sites. Give it a list of companies
(an ATS board URL, an ats:slug, or just the company's careers page) and it returns every
open role as flat JSON — with a stable dedupKey, ISO timestamps and filters, so you can
run it on a schedule and get only the roles that are new since last time.
No login, no API key, no proxy. Each supported ATS publishes a public JSON endpoint that companies use to syndicate their own postings. This actor reads those endpoints and nothing else, which is why it's fast and doesn't break the way page scrapers do.
Supported ATS platforms
| ATS | What you can pass | Descriptions |
|---|---|---|
| Greenhouse | greenhouse:stripe, https://boards.greenhouse.io/stripe, job-boards.greenhouse.io/…, EU boards | ✔ (includeDescription) |
| Lever | lever:spotify, https://jobs.lever.co/spotify, EU boards | ✔ |
| Ashby | ashby:notion, https://jobs.ashbyhq.com/notion | ✔ (+ published compensation) |
| Workable | workable:acme, https://apply.workable.com/acme, acme.workable.com | ✖ (list endpoint only) |
| SmartRecruiters | smartrecruiters:BoschGroup, https://jobs.smartrecruiters.com/BoschGroup | ✖ (list endpoint only) |
Any careers page URL (https://acme.com/careers) also works: the actor fetches the page,
finds the embedded board of any of the five ATSs, and continues from there. If a page uses an
unsupported ATS you get a warning naming the URL, never a silent empty result.
What it does
- Resolves each company entry to an ATS board (explicit, by URL, or by page discovery).
- Reads the board's public JSON API, following pagination where the ATS paginates.
- Normalises every posting into the same flat record regardless of ATS.
- Applies your filters — title keywords, excluded keywords, locations (incl.
remote),postedAfter. - Deduplicates within the run and pushes one record per posting, up to
maxItems.
Input
| Field | Type | Default | Notes |
|---|---|---|---|
companies | array of strings | — | Required. ATS URLs, ats:slug, or careers page URLs |
keywords | array | [] | Keep postings whose title contains any keyword (case-insensitive) |
excludeKeywords | array | [] | Drop postings whose title contains any of these |
locations | array | [] | Substring match on location; include "remote" to also keep remote-flagged roles |
postedAfter | string | — | ISO date/date-time. Drops older postings; keeps postings with no date |
includeDescription | boolean | false | Adds plain-text descriptionText (Greenhouse, Lever, Ashby) |
maxItems | integer | 500 | Billing guardrail — hard cap on postings pushed per run |
proxyConfiguration | object | off | Not needed for these APIs; enable only at very high volume |
Example — every engineering role at four companies, UK or remote, posted this month:
{"companies": ["greenhouse:stripe", "https://jobs.lever.co/spotify", "https://jobs.ashbyhq.com/notion", "https://jobs.smartrecruiters.com/BoschGroup"],"keywords": ["engineer"],"locations": ["United Kingdom", "London", "remote"],"postedAfter": "2026-08-01","maxItems": 200}
Output
One JSON object per posting in the default dataset:
| Field | Type | Description |
|---|---|---|
source | string | greenhouse | lever | ashby | workable | smartrecruiters |
company | string | Board slug on that ATS |
companyName | string | null | Display name when the ATS provides it |
jobId | string | Posting ID on the ATS |
title | string | Job title |
location | string | null | Location text |
isRemote | boolean | ATS remote flag, or inferred from the location text |
department, team | string | null | When the ATS provides them |
employmentType | string | null | e.g. Full-time |
compensation | string | null | Published pay range (Ashby) |
postedAt | string | null | ISO 8601 publish date |
updatedAt | string | null | ISO 8601 last update (Greenhouse) |
url, applyUrl | string | Public posting / apply links |
descriptionText | string | null | Plain text, only with includeDescription |
dedupKey | string | Stable key source:company:jobId |
scrapedAt | string | ISO 8601 |
Monitoring: new roles since last run
dedupKey never changes for a given posting, so the recipe is:
- Schedule the actor (daily works well; hourly for hot accounts).
- Either set
postedAfterto the previous run's time, or diff each run's dataset against the last one ondedupKey— new keys are new roles, missing keys are closed roles. - Send the difference wherever you like (Slack, email, a Google Sheet) with an Apify integration.
Typical uses: hiring-signal alerts for sales and recruitment teams, tracking competitor hiring, feeding a niche job board, watching a shortlist of dream companies.
Pricing
Pay per event: one charge per posting pushed to the dataset. Postings removed by your
filters are free. maxItems caps the spend of any single run.
Notes & limitations
- Workable and SmartRecruiters list endpoints don't include descriptions;
includeDescriptionis ignored for them. - A board that returns 404 (wrong slug, or the company moved to a different ATS) is reported in the log and skipped — it doesn't fail the run.
- Discovery reads the careers page HTML you give it. Boards injected by client-side JavaScript that never appear in the HTML source can't be found that way — pass the board URL directly.
- Sources are the ATSs' own public APIs; the actor sends a descriptive User-Agent and backs off on 429.
Development
npm installnpm test # unit tests (parsers, normalisers, filters — no network)apify run # local run with storage/key_value_stores/default/INPUT.json