ATS Job Feeds — Greenhouse, Lever & Ashby jobs
Pricing
from $1.40 / 1,000 job postings
ATS Job Feeds — Greenhouse, Lever & Ashby jobs
Collect job postings from companies' public Greenhouse, Lever and Ashby job boards into one normalised dataset, with an optional mode that returns only jobs that are new since the last run.
Pricing
from $1.40 / 1,000 job postings
Rating
0.0
(0)
Developer
AI Mojo
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
3 days ago
Last modified
Categories
Share
Greenhouse, Lever and Ashby jobs API — one normalised job feed
ATS Job Feeds collects job postings from any company's public Greenhouse, Lever or Ashby job board and returns them in one normalised format, so a Greenhouse job and a Lever job have the same fields. Turn on Only new jobs since the last run to get just the job postings that appeared since your previous run. To try it, press Start: the prefilled companies return results in under a minute.
How to scrape Greenhouse, Lever and Ashby job postings
- Find each company's job-board slug (see How to find a company's slug below).
- Add one line per company to Companies, written as
<ats>:<company-slug>, for examplegreenhouse:airbnb,lever:palantirorashby:openai. - Optionally set Maximum jobs per company, Only new jobs since the last run and Include job descriptions.
- Press Start and wait for the run to finish. The status message shows how many companies and job postings are done.
- Open the Output tab to view the job postings, then download them as JSON, CSV, Excel, XML or HTML.
- To automate it, call the actor through the Apify API, or connect it to Make, Zapier, Google Sheets, Slack or a webhook with Apify integrations.
Input
| Field | Type | Default | Description |
|---|---|---|---|
companies | array of strings | none (required) | Companies whose public job boards to collect, one per line, written as <ats>:<company-slug>. The ATS is greenhouse, lever or ashby. |
maxJobsPerCompany | integer | 0 | The most job postings to return for each company. 0 means no limit. |
onlyNew | boolean | false | When on, returns only job postings that were not seen in previous runs with the same company list. |
includeDescription | boolean | true | When on, each job posting includes its full description as HTML and as plain text. Turn off for smaller, faster results. |
Example input (the prefilled values):
{"companies": ["greenhouse:airbnb", "lever:palantir", "ashby:openai"],"maxJobsPerCompany": 5,"onlyNew": false,"includeDescription": true}
How to find a company's slug
Open the company's careers page and follow a link to one of its jobs. The slug is the path segment straight after the job-board host:
- Greenhouse:
boards.greenhouse.io/<slug>(for exampleboards.greenhouse.io/airbnb→greenhouse:airbnb) - Lever:
jobs.lever.co/<slug>(for examplejobs.lever.co/palantir→lever:palantir) - Ashby:
jobs.ashbyhq.com/<slug>(for examplejobs.ashbyhq.com/openai→ashby:openai)
Output
Each dataset item is one job posting with the same fields, whichever job board it came from. Fields the job board does not give are null.
| Field | Type | Description |
|---|---|---|
id | string | Stable job posting ID in the form <ats>:<company-slug>:<native-id>. It stays the same across runs. |
ats | string | The applicant-tracking system (job board) the posting came from: greenhouse, lever or ashby. |
companySlug | string | The company's job-board slug, as given in the companies input. |
title | string | The job posting's title. |
url | string | Link to the job posting on the company's public job board. |
companyName | string or null | The company's display name. |
applyUrl | string or null | Link to the job application form. |
locations | array of strings | Every location listed for the job posting. Empty when the job board lists none. |
department | string or null | The department the job belongs to. |
team | string or null | The team the job belongs to. |
employmentType | string or null | The employment type as the job board states it, for example full-time or contract. |
workplaceType | string or null | Whether the job is remote, hybrid or onsite. |
publishedAt | string or null | When the job posting was published (ISO 8601). |
updatedAt | string or null | When the job posting was last updated (ISO 8601). |
compensation | string or null | The pay range or compensation summary as the job board states it. |
descriptionHtml | string or null | The full job description as HTML; null when descriptions are not included. |
descriptionText | string or null | The full job description as plain text; null when descriptions are not included. |
scrapedAt | string | When this run collected the job posting (ISO 8601). |
Example job posting (from an Ashby job board, descriptions shortened):
{"id": "ashby:openai:dbd5ae8a-7c01-4f17-be39-b8caa8fd95d5","ats": "ashby","companySlug": "openai","title": "Recruiting Coordinator - Contract","url": "https://jobs.ashbyhq.com/openai/dbd5ae8a-7c01-4f17-be39-b8caa8fd95d5","companyName": null,"applyUrl": "https://jobs.ashbyhq.com/openai/dbd5ae8a-7c01-4f17-be39-b8caa8fd95d5/application","locations": ["San Francisco", "New York City", "Seattle"],"department": "People","team": "Recruiting","employmentType": "Contract","workplaceType": "remote","publishedAt": "2026-08-28T18:45:07.651Z","updatedAt": null,"compensation": "$57 – $70 per hour","descriptionHtml": "<p><strong>About the Role</strong></p><p>We’re seeking a Contract Recruiting Coordinator to join our team…</p>","descriptionText": "About the Role\n\nWe’re seeking a Contract Recruiting Coordinator to join our team…","scrapedAt": "2026-10-11T12:00:00.000Z"}
The run also saves a short summary (job postings per company, and which companies failed) in the Run summary output.
Only new postings
With Only new jobs since the last run (onlyNew) turned on, the actor remembers the IDs of the job postings it has seen (up to the most recent 50,000) and returns only the ones it has not seen before. The memory is kept per exact company list: the same companies (in any order) share it, and a different list starts fresh. It is stored in a named key-value store in your own Apify account, so you can view or delete it at any time. The first run with a new company list returns every current job posting. Every fetched posting is remembered, including ones left out by Maximum jobs per company, so later runs return only postings that appeared after that run. Postings left out because the run reached your maximum charge are not remembered, so the next run offers them again.
The memory holds at most 50,000 job posting IDs per company list. When it is full, the IDs that were first seen longest ago are dropped first, even if those postings were fetched again in recent runs. If a dropped posting is still listed on the job board, a later run treats it as new and delivers it again, and you are charged for it again. This can happen only when a posting stays listed while more than 50,000 newer posting IDs (first seen after it) are seen for the same company list; if your list is that large, split it into smaller lists.
Tip: create an Apify Schedule that runs the actor daily with onlyNew on, and you get a daily feed of new job postings.
Pricing
This actor uses pay-per-event pricing: you pay for each job posting delivered to your dataset, and nothing for pages or requests.
How much does it cost to get 1,000 job postings?
$2.00 per 1,000 job postings ($0.002 per job posting), lower on paid Apify plans.
- You're charged only for job postings delivered to your dataset. With
onlyNewon, postings the actor still remembers are not delivered or charged again (see the 50,000-ID memory limit under Only new postings). - The run stops when it reaches your maximum charge per run setting, so you never pay more than you set.
- Apify adds a small fee for each run start.
Use cases
- Job aggregators and job boards: fill a niche job board from hundreds of company career pages in one format.
- Recruiting and sourcing: watch target companies for new openings in your specialty.
- Hiring-signal sales intelligence: spot companies that are hiring for roles that need your product.
- Market research: track hiring trends by company, department, location or workplace type.
Limits & compliance
- Uses only the public job-board endpoints that Greenhouse, Lever and Ashby publish for third-party use.
- Sends at most 1 request per second to each vendor, and identifies itself with its own user agent.
- Needs no login, API key or account on any job board.
- Collects no personal data beyond what employers publish in their job postings.
FAQ
Is it legal to collect job postings from Greenhouse, Lever and Ashby?
The actor reads only job postings that employers publish on public job boards, through endpoints the vendors provide for third-party use, and collects no personal data beyond what is in those postings. You are still responsible for how you use the data; if you are unsure, ask a lawyer about your use case.
What happens if a company slug is wrong or unknown?
The company is skipped and a message is written to the run log. The other companies still run.
What if a company changed its ATS?
Its old board returns no job postings and is logged. Find the new job board as described in How to find a company's slug and update the entry, for example from lever:acme to ashby:acme.
How fresh is the data?
Every run reads the job boards live, so the job postings are as current as the company's board at the time of the run.
Where can I report an issue or request a feature?
Open the Issues tab on this actor's page and describe the company entries and what you expected.