Greenhouse, Lever & Ashby Jobs API + Hiring Signals
Pricing
from $1.50 / 1,000 jobs
Greenhouse, Lever & Ashby Jobs API + Hiring Signals
Career Site Jobs API for Greenhouse, Lever, Ashby, Workday and 5 more ATSs. Domain in: open jobs, new/closed jobs, or one flat hiring-signals row for Clay, CRMs and AI agents. Pay only for jobs and signals you use.
Pricing
from $1.50 / 1,000 jobs
Rating
0.0
(0)
Developer
North Loop Agents
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
2 hours ago
Last modified
Categories
Share
Greenhouse jobs API + hiring signals for Clay (also Lever, Ashby, Workday)
Jobs API for Greenhouse, Lever, Ashby, Workday, Workable, Personio, SmartRecruiters, Teamtailor and Recruitee. Give it company domains. It finds each company's ATS, reads its public job board and returns either every open job as clean JSON, only the new and closed jobs since your last run, or one flat hiring-signal row per domain (open jobs, new jobs, closed jobs, top departments, top locations, sample titles and URLs) that drops straight into Clay, a CRM or an AI agent.
- Domain in, signal out.
stripe.comin, one row out:openJobs,newJobs,closedJobs,newJobsLast7d,topDepartments,topLocations,sampleTitles,newJobUrls. Flat fields only, no nested arrays, so Clay mapping is one click per column. - Pay only for what's new. Change tracking is stored in your own Apify account. Jobs you already received are never charged again, and a company that didn't change costs $0.
- No browser, no proxy, no login. Official public job-board APIs only, the same endpoints the companies' own career pages call. Fast, cheap and stable.
- Built for agents. Pay per event, events only, limited permissions, no Standby: it can be run by AI agents through the Apify MCP server and the Apify API.
Quick start
{"mode": "signals","domains": ["notion.so", "n26.com", "pleo.io"]}
That's the whole input. Example output row (shortened):
{"recordType": "hiring-signal","input": "n26.com","company": "N26","ats": "greenhouse","boardUrl": "https://job-boards.greenhouse.io/n26","status": "ok","changed": true,"openJobs": 37,"newJobs": 2,"closedJobs": 1,"netChange": 1,"newJobsLast7d": 5,"newJobsLast30d": 15,"topDepartments": "Finance (5); Group Internal Audit (5); Risk (3); Legal (3); Business (2)","topLocations": "Berlin, DE (20); Barcelona, ES (9); Madrid, ES (5); Paris, FR (3)","newJobTitles": "Treasury Trader; ICT Risk Assessment Manager","newJobUrls": "https://job-boards.greenhouse.io/n26/jobs/… | https://job-boards.greenhouse.io/n26/jobs/…","summary": "N26 opened 2 and closed 1 job(s) since 2026-10-22; most new roles in Treasury.","checkedAt": "2026-10-23T05:40:12.000Z","billedEvent": "hiring-signal"}
Modes and price per result
You pay per event, and only for events. No platform-usage surcharge, no per-company fee.
| Mode | What you get | Price |
|---|---|---|
signals | One flat hiring-signal row per domain | $0.025 per changed domain. A domain counts as changed on its first check (if it has open jobs) and afterwards only when jobs were opened or closed since your last check. Unchanged, zero-job and not-found domains get a free row. |
jobs (default) | Every open job matching your filters, one row per job | $0.0015 per job ($1.50 per 1,000 jobs) |
new-jobs | Only jobs that are new or closed since your last run | $0.0015 per new or closed job. Jobs already delivered are never charged again. |
new-jobs-and-signals | Both of the above | Both of the above |
Apify also charges its standard actor-start event ($0.00005 per run, which pays for the first 5 seconds of compute).
Examples:
- Enrich 1,000 Clay rows once: if 800 of the domains have open jobs, 800 × $0.025 = $20. Domains with no jobs or no ATS cost nothing.
- Re-check the same 1,000 domains every week: you pay only for the ones that changed, typically a fraction of the list.
- Daily new-jobs feed for 50 companies with about 40 new or closed jobs a day: 40 × $0.0015 = $0.06/day.
Set Maximum cost per run in the run options. The Actor stops cleanly at your limit, and anything it couldn't deliver is still "new" next time, so you never pay for rows you didn't get.
Reliability
Tested on 23+ platform runs before launch, with 0 failures (21–24 Oct 2026: our own test and validation runs across Greenhouse, Lever, Ashby, Workday and Personio). The "runs succeeded" figure on the Store page counts only other users' runs from the last 30 days, so it reads 0% until the first public runs come in.
Every row comes from an official public ATS API, so there are no CAPTCHAs, proxies or browser crashes to fail on. A domain whose ATS can't be found is reported as a free not-found row; it doesn't fail the run.
Use it in Clay
Clay's native Run Apify Actor enrichment works on every Clay plan, Free included. It runs on your own Apify account, so you only need an Apify API token.
- Create a Task in Apify. Open this Actor in Apify Console, click Create task, switch the input from Manual to JSON and paste:
Save the task (for example "Hiring signal for one domain").{ "mode": "signals", "domains": ["stripe.com"] } - Connect Apify in Clay (once). In Clay go to Settings → Connections → Add connection → Apify and paste your Apify API token from Apify Console → Settings → API & Integrations. You can also add it from the enrichment panel the first time.
- Add the enrichment. In your Clay table click Add enrichment, search for Apify and choose Run Apify Actor. Pick your Apify account and the task from step 1.
- Map the domain column. In Input Data enter the JSON body and insert your domain column as a token (type
/and pick the column):
Clay's rule: keep the key in quotes but don't put quotes around the token. (If Clay reports invalid JSON for your column type, wrap the token in quotes.){ "mode": "signals", "domains": [ /Company Domain ] } - Control spend. Turn auto-update off while you test, and use a conditional run (for example, only when Company Domain is not empty) so you only pay for rows you want.
- Run and map columns. Run the column on a few rows, open a cell and click the fields you want as new columns:
openJobs,newJobs,closedJobs,newJobsLast7d,topDepartments,topLocations,sampleTitles,newJobUrls,summary. Every field is a plain string, number or boolean. - Make it a weekly signal. Re-run the column every week (scheduled re-runs on Clay's paid plans, or manually). Each re-run compares the domain with its last check, so
newJobs/closedJobsshow what changed that week, and unchanged domains cost $0.
Good Clay triggers: newJobs >= 3, hiringSurge = true, newJobsTopDepartments contains "Sales" or "Engineering", topLocations contains your territory.
Clay Growth plan: HTTP API instead. POST https://api.apify.com/v2/acts/northloop-hq~jobs-api-ats-feed/run-sync-get-dataset-items?maxTotalChargeUsd=0.05 with the header Authorization: Bearer <your Apify token> and the JSON body above. The call returns the dataset rows directly; it must finish within 300 seconds, which one or a few domains always do.
Clay Free plan tables hold up to 200 rows.
For AI agents and developers
- Input:
domains(array of domains),mode(signals|jobs|new-jobs|new-jobs-and-signals), optional filters (keywords,countries,departments,workplaceTypes,employmentTypes,seniorities,postedWithin). - Output: dataset rows with
recordType=hiring-signalorjob. Run summary (per-company status, charged events, estimated charge) in theOUTPUTkey-value record. - Sync call:
POST /v2/acts/northloop-hq~jobs-api-ats-feed/run-sync-get-dataset-itemsreturns rows in one request. - Agent payments: pay-per-event, events only, limited permissions, no Standby, which is what Apify requires for agentic payments (x402 and pay-per-request agents).
- State: change tracking lives in the named key-value store
jobs-api-ats-feed-statein the caller's own account, per company and per filter set (or permonitorId). Deleting that store resets it.
Output: hiring-signal rows
One row per input domain per run (recordType: "hiring-signal"), in every mode that includes signals.
| Field | Meaning |
|---|---|
input, companyDomain, company | What you passed, the domain, and the company name from the job board |
ats, atsSlug, boardUrl | Detected ATS, board name and public board URL |
status, error | ok, not-found, error, duplicate or invalid-input, plus the reason |
changed, billedEvent | Whether this row was charged (hiring-signal) or free (null) |
isFirstSnapshot | true on the first check of this domain for this watch list |
openJobs, openJobsBefore | Open jobs now and at the last check |
newJobs, closedJobs, netChange, growthPct | Changes since the last check (null on the first snapshot) |
hiringSurge | true when at least 5 jobs and at least 10% of the previous open jobs were opened |
newJobsLast7d, newJobsLast30d | Open jobs posted in the last 7 / 30 days (from ATS dates; works on the first run) |
remoteJobs, remotePct | Remote open jobs |
topDepartments, topLocations, topCountries | Top 5 of all open jobs, e.g. "Engineering (12); Sales (5)" |
newJobsTopDepartments, newJobsTopLocations | Top 5 of the new jobs |
sampleTitles, sampleJobUrls | 5 newest open titles / URLs |
newJobTitles, newJobUrls, closedJobTitles | Up to 10 new titles / URLs and closed titles |
latestPostedAt, periodStart, checkedAt, lastChangeAt | Dates (ISO 8601) |
summary | One sentence, ready for an email opener or a Slack alert |
Lists inside a field are joined with "; " (titles) or " | " (URLs).
Output: job rows
One row per job (recordType: "job"). Example, with the description shortened:
{"recordType": "job","company": "Pleo","companyDomain": "pleo.io","ats": "ashby","atsSlug": "pleo","jobId": "5b0f0144-e153-4468-a626-3baf79e2342c","jobKey": "ashby:pleo:5b0f0144-e153-4468-a626-3baf79e2342c","title": "Sales Development Representative - Nordics","department": "SDR","city": "Lisbon","countryCode": "PT","countryCodes": ["PT", "DK"],"workplaceType": null,"employmentType": "FULL_TIME","seniority": null,"salaryMin": null, "salaryMax": null, "salaryCurrency": null, "salaryPeriod": null,"postedAt": "2026-10-20T09:14:57.321Z","jobUrl": "https://jobs.ashbyhq.com/pleo/5b0f0144-e153-4468-a626-3baf79e2342c","applyUrl": "https://jobs.ashbyhq.com/pleo/5b0f0144-e153-4468-a626-3baf79e2342c/application","descriptionMarkdown": "## **About Pleo**\n\nMessy spend management is tricky business. …","status": "open","changeType": null,"firstSeenAt": "2026-10-21T06:21:34.020Z","resolvedBy": "careers-page-link"}
Values are normalised across all ATSs:
- employmentType: FULL_TIME, PART_TIME, CONTRACT, TEMPORARY, INTERNSHIP, WORKING_STUDENT, APPRENTICESHIP, FREELANCE
- seniority: INTERN through EXECUTIVE. It comes from the title, or from the ATS field when the title has no hint.
- workplaceType: remote, hybrid or onsite
- Countries: ISO 3166 alpha-2 codes. Country names in many languages are recognised, as are US-state formats ("Austin, TX") and Workday's "USA, CA, Santa Clara".
- Salary: filled in when the company publishes it (Ashby, Lever, Recruitee).
In new-jobs modes, job rows carry changeType: "new" or "closed" (with closedAt). A job that only falls outside your date filter is not reported as closed.
Supported ATSs
| ATS | Typical customers | Public endpoint used |
|---|---|---|
| Greenhouse | US/EU tech (Airbnb, Stripe, Figma, Datadog…) | boards-api.greenhouse.io/v1/boards/{board}/jobs (Job Board API) |
| Lever | Tech scale-ups (Spotify, Palantir…) | api.lever.co/v0/postings/{site} (Postings API, US and EU instances) |
| Ashby | Start-ups (Notion, Pleo, OpenAI…) | api.ashbyhq.com/posting-api/job-board/{board} (Job Posting API) |
| Workday | Enterprises (NVIDIA, Salesforce, Adobe, Workday…) | {tenant}.wdN.myworkdayjobs.com/wday/cxs/… (the career site's own JSON API) |
| Workable | SMBs worldwide | apply.workable.com/api/v1/widget/accounts/{account} |
| Personio | DACH SMEs and scale-ups | {company}.jobs.personio.de/xml (official XML feed) |
| SmartRecruiters | Large enterprises (Bosch, Visa…) | api.smartrecruiters.com/v1/companies/{id}/postings (Posting API) |
| Teamtailor | Nordics, Benelux, UK | Career-site RSS /jobs.rss (custom domains work too) |
| Recruitee | Netherlands, CEE | {company}.recruitee.com/api/offers/ |
How auto-detection works
- The Actor opens the website and up to 6 career-related pages and looks for links, embeds or redirects to one of the 9 ATSs, including Workday career sites the company links to.
- If nothing is found, it tries the company name as a board name on each ATS. It accepts the guess only when the board's company name matches the domain, or when exactly one board exists. Each row says how its company was resolved (
resolvedBy). - Resolutions are cached in your account for 30 days, and domains without a detectable ATS for 1 day.
You can also pass job-board URLs or ats:slug entries (greenhouse:airbnb, lever:spotify, ashby:pleo, workday:nvidia.wd5/NVIDIAExternalCareerSite) in the companies field.
Privacy and data protection
- The Actor only outputs job advertisements. It never copies recruiter or contact fields (e.g. SmartRecruiters
creator, Recruiteemailbox_email). - Personal e-mail addresses and phone numbers in descriptions are removed. Role mailboxes such as
careers@are kept. - Names of people in free text can't be detected reliably. If you republish descriptions, review them for that.
Limits and notes
- Only published jobs are covered. Internal and hidden jobs aren't in the public feeds.
- Workday:
- Pass the career-site URL (e.g.
https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite) orworkday:tenant.wdN/site. A bare domain is only detected when the company's site links to its Workday career site. - Workday shows at most 2,000 jobs per search. Larger tenants are flagged
truncated; use keywords to narrow the search. - Requests are rate-limited (about 2.5/s per site) to be polite, so large tenants take 1–4 minutes.
- Country, remote and employment-type filters need one detail request per candidate job, capped by
maxDetailRequestsPerCompany. - Turn off
workdayDepartmentsfor faster runs without department labels.
- Pass the career-site URL (e.g.
- SmartRecruiters: descriptions need one request per job, so they're only fetched for jobs that are output. Listing is capped at 5,000 jobs.
- Teamtailor: the RSS feed has no employment type or salary.
- Personio: descriptions are requested in English, with the company's default language as a fallback.
- Career sites built entirely in JavaScript may not be auto-detected. Pass the board URL or
ats:sluginstead.
FAQ
Is this legal? The Actor reads the public endpoints that ATS vendors provide so companies can show their jobs on their own websites. It doesn't log in, doesn't bypass protections and collects no personal data. You remain responsible for how you use the data.
Can I use it as an API? Yes. Call it through the Apify API, SDKs, or MCP from your own code or AI agent, and read the dataset as JSON or CSV. See For AI agents and developers above.
My company isn't detected or its ATS isn't supported. Pass the job-board link or ats:slug. For other ATSs (SAP SuccessFactors, iCIMS, Join…), open an issue and tell us which one you need.