ATS Hiring Signals Monitor — Greenhouse, Lever & Ashby
Pricing
from $4.00 / 1,000 job results
ATS Hiring Signals Monitor — Greenhouse, Lever & Ashby
Hiring signals for B2B sales and recruiting: new job postings per company from the official public Greenhouse, Lever and Ashby job-board APIs. Batch of company slugs, diff mode (new within N days), filters. No login. Not affiliated with the ATS vendors.
Pricing
from $4.00 / 1,000 job results
Rating
0.0
(0)
Developer
Johnn Mottin
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
4 days ago
Last modified
Categories
Share
"Company X just opened a role for Y" is a buying signal — a company hiring devs is about to buy dev tools; a company hiring SDRs is about to buy sales tools. This Actor turns the official public job-board APIs of Greenhouse, Lever and Ashby into that signal: give it a list of companies, get back only the jobs published in the last N days, normalized across the three ATSs. No login, no browser, no LinkedIn.
Not affiliated with, sponsored by, or endorsed by Greenhouse, Lever, Ashby, or any company whose job board is queried. All data comes from the official public job-board APIs those companies expose and remains subject to their terms.
Who it's for:
- B2B sales / outbound teams (SDRs): wake up to "these 4 of my 80 target accounts posted new engineering roles this week" — in your CRM, Slack or spreadsheet via Apify integrations.
- Recruiting agencies: monitor client and prospect boards for new mandates before anyone calls.
- Analysts / founders: track hiring velocity of competitors as a growth proxy.
How it works
You provide company board slugs (e.g. stripe — the identifier in the company's careers URL). For each company, the Actor queries the official API of its ATS — or auto-detects the ATS by trying Greenhouse → Lever → Ashby (cheap 404s). Default mode is the signal: only jobs first published within newWithinDays (computed at run time, so a saved schedule never goes stale). One unknown slug never kills the batch — it becomes a controlled NOT_FOUND in STATS.companySummary.
You are only charged for jobs actually written to the dataset — jobs discarded by the date window, filters or caps cost you nothing.
Input
Copy-paste ready (weekly signal over 3 boards):
{"companies": [{ "slug": "stripe" },{ "slug": "gitlab", "ats": "greenhouse" },{ "slug": "spotify", "ats": "lever" }],"newWithinDays": 7,"titleKeywords": ["engineer", "developer", "data"],"remoteOnly": false}
| Field | Type | Default | Description |
|---|---|---|---|
companies | array | required | 1–100 {slug, ats?} objects. ats: greenhouse | lever | ashby | auto (default). Unknown slug → controlled NOT_FOUND; duplicates skipped |
newWithinDays | int 1–365 | 7 | The signal window: only jobs first published in the last N days (Greenhouse first_published, Lever createdAt, Ashby publishedAt). Ignored when fullDump is on |
fullDump | boolean | false | Return every job currently on each board (ignores the date window) — a one-off full export instead of the signal |
titleKeywords | string[] | [] | Any keyword may match the title (case-insensitive). Discarded = never billed |
departments | string[] | [] | Substring on department/team. On Greenhouse triggers the heavier content fetch automatically |
locations | string[] | [] | Substring on location(s) — e.g. "london", "remote", "brazil" |
remoteOnly | boolean | false | Only jobs explicitly remote (Ashby isRemote, Lever workplaceType; Greenhouse via location text — best-effort) |
includeDescription | boolean | false | Adds the job description (bigger records) |
maxJobsPerCompany | int 1–2000 | 500 | Newest first |
maxResults | int 1–5000 | 1000 | Run-wide hard cap |
Output (missing = null / [], never invented)
One record per job, same key set across the three ATSs. Real record (GitLab, official public data):
{"atsSource": "greenhouse","companyIndex": 1,"companySlug": "gitlab","jobId": "8115023002","title": "Account Executive - Italy","department": null,"team": null,"employmentType": null,"location": "Remote, Italy","secondaryLocations": [],"isRemote": true,"workplaceType": null,"url": "https://job-boards.greenhouse.io/gitlab/jobs/8115023002","publishedAt": "2026-06-11T20:23:44.000Z","publishedAtRaw": "2026-06-11T16:23:44-04:00","updatedAt": "2026-07-17T12:48:22.000Z","compensation": null,"description": null,"scrapedAt": "2026-07-30T12:00:00.000Z"}
| Field group | Fields | Notes |
|---|---|---|
| Correlation | atsSource, companyIndex, companySlug | ties every job to your input list |
| Job | jobId, title, department, team, employmentType, url | core fields¹: title, url, publishedAt, atsSource, companySlug |
| Location | location, secondaryLocations[], isRemote, workplaceType | isRemote is native on Ashby/Lever; text heuristic on Greenhouse (best-effort) |
| Dates | publishedAt (+Raw), updatedAt (Greenhouse only) | ISO, parsed from each ATS's native format (ISO-with-offset / epoch-ms / ISO) |
| Extras | compensation (Ashby, when the company exposes it), description (opt-in) |
¹ Watched by the built-in health check: if more than 50% come back null the run fails loudly naming the dead field (DEAD_FIELDS) — never a silent broken dataset.
Availability by ATS (measured on real boards, 2026-07): department/team — always on Lever/Ashby, Greenhouse only with the content fetch; compensation — Ashby only, when the company enables it; updatedAt — Greenhouse only.
Run health
STATS (key-value store) records per-company outcomes (companySummary: OK, NO_JOBS, NOT_FOUND, FAILED, INVALID_COMPANY, DUPLICATE_SKIPPED, SKIPPED_MAX_RESULTS, plus detectedAts for auto mode), HTTP counters, retries and discard counters (discardedByDate / discardedByFilters / discardedByCap / discardedNoDate). ERRORS records failures with stable codes (INVALID_INPUT, NOT_FOUND, HTTP_UNAVAILABLE, HTTP_TIMEOUT, HTTP_RATE_LIMITED, API_CONTRACT_CHANGED, DEAD_FIELDS, ALL_COMPANIES_FAILED).
- A week with no new postings on a quiet board is a legitimate result (
STATS.legitimateNoNewJobs) — that's what a monitor is for. - A batch where no company completes fails loudly with
ALL_COMPANIES_FAILED.
API usage examples
Run and get items in one call:
curl -s "https://api.apify.com/v2/acts/<YOUR_USERNAME>~ats-hiring-signals-monitor/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \-X POST -H "Content-Type: application/json" \-d '{"companies":[{"slug":"stripe"}],"newWithinDays":7}'
Weekly account-list watch (Console → Schedules): save your 50–100 target accounts as input with newWithinDays: 7 and schedule for Monday morning — the relative window recomputes every run.
Recruiting mandate radar:
{"companies": [{ "slug": "ramp" }, { "slug": "linear" }],"newWithinDays": 14,"departments": ["sales", "marketing"]}
Schedule it (recommended — cloud, not your desktop)
New postings are a weekly signal — newWithinDays: 7 plus a weekly cron. Use Apify's own Schedules, not a local scheduler — configure it once and it runs in the cloud whether or not your machine is on.
- Save your input as a Task (Console → this Actor → Create task), e.g. your 50–100 target accounts with
newWithinDays: 7. - Console → Schedules → Create schedule, add the Task, set the cron (e.g. Mondays 6am →
0 6 * * 1). - Route the dataset to Slack, Sheets, your CRM or webhook via Apify integrations.
The date window is computed at run time, so a saved schedule never goes stale — Monday's run always asks for last week's postings.
Pricing
Billed per job written to the dataset (Pay Per Event) — the Pricing tab on this page is always the authoritative source for current rates and for any per-run fee. Jobs discarded by the window, filters or caps are never billed. newWithinDays is the main cost lever: the signal mode typically writes a handful of jobs per company per week.
Honest limits
- You supply the company list. No ATS publishes a public directory of its boards; the slugs come from your target accounts (careers-page URLs).
- Coverage = Greenhouse + Lever + Ashby. Companies on Workday, SmartRecruiters, iCims etc. return
NOT_FOUNDin auto mode. More ATSs are a natural expansion. publishedAtsemantics differ slightly per ATS (Greenhouse first publication, Lever creation, Ashby publication) — all fresh enough for weekly signals; raw values are preserved.- Greenhouse
departmentneeds the heavier fetch — triggered automatically only when you filter by department or ask for descriptions. - Remote detection on Greenhouse is text-based (best-effort) — native flags exist only on Lever/Ashby.
- The Actor is deliberately polite with the APIs: 2 concurrent requests, pacing, exponential backoff on 429/5xx, batches capped at 100 companies per run.
FAQ
Do I need an account or API key for Greenhouse, Lever or Ashby? No. The Actor reads the official public job-board APIs those companies expose, without logging in.
Where do I find a company's slug? In its careers page URL: boards.greenhouse.io/<slug>, jobs.lever.co/<slug>, jobs.ashbyhq.com/<slug>. There is no public directory of all companies per ATS — your target-account list is the input, which is exactly how outbound works.
What exactly am I charged for? Per job written to the dataset (Pay Per Event) — jobs discarded by the date window, filters or caps cost you nothing. The Pricing tab on this page is always the authoritative source for current rates and for any per-run fee.
Can I schedule it? Yes — that is the intended use. See "Schedule it" above.
Is this affiliated with the ATS vendors? No. This is an unofficial community Actor, not affiliated with Greenhouse, Lever, Ashby or any company whose job board is queried; all data comes from their official public APIs and remains subject to their terms.