ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API
Pricing
$3.00 / 1,000 jobs
ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API
Search 328,000+ open jobs from 11,000+ companies on Greenhouse, Lever and Ashby in one run. Filter by keyword, location, remote, salary, seniority and posting date. Flat rows with annual salary, days open and company hiring velocity. Lead-list mode and daily new-jobs monitor.
Pricing
$3.00 / 1,000 jobs
Rating
0.0
(0)
Developer
Redomic
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
13 hours ago
Last modified
Categories
Security
Limited permissionsShare
Search 328,829 open jobs across 11,242 companies on Greenhouse, Lever and Ashby in one run. Updated daily. 152,559 with a salary.
Type what you are looking for once, across every company, instead of scraping one careers page at a time:
- "every remote data engineer job with a USD salary"
- "all new sales roles first seen this week, one row per company" (a lead list)
- "Python jobs in Berlin, sent to me only when a new one appears" (a daily monitor)
No scraping happens at run time: you search our own daily snapshot of 11,000+ career sites (5,838 Greenhouse, 3,501 Ashby, 1,903 Lever companies), so a full search over every open job finishes in seconds and never gets blocked.
What you get that a live scraper can't give you
| Field | What it tells you |
|---|---|
salaryAnnualMin, salaryAnnualMax | Pay normalised to a yearly number (hourly x 2080, monthly x 12), so you can sort and filter across companies. A yearly figure a company mis-tagged as monthly or hourly is kept as yearly, not multiplied |
daysOpen | Days since the job first appeared in our daily crawl (openSinceBeforeTracking = it was already open when tracking began). For closed jobs, this is firstSeen to closedOn |
closedOn | The day a job disappeared from its board (null while open). With daysOpen, this is time-to-fill for roles that closed |
companyOpenRoles | How many jobs this company has open right now, across all its roles |
companyNewRoles7d | How many new roles the company opened in the last 7 days: a hiring-velocity signal for sales and recruiting |
firstSeen | The day the job first appeared, even when the company never shows a posted date |
locationCount, otherLocations | The same role posted in many cities comes back once, with every location listed (and is billed once) |
evergreen | Still open more than 180 days after posting: usually a standing ad, not a fresh opening |
Sample output (real run, 5 Nov 2026)
Input: {"keywords": ["data engineer"], "remoteOnly": true, "hasSalary": true, "salaryCurrency": "USD", "maxItems": 5}
matched 124 of 328,829 open jobs.
| company | title | location | salaryAnnualMin | salaryAnnualMax | postedAt | companyOpenRoles | companyNewRoles7d |
|---|---|---|---|---|---|---|---|
| Natera | Senior Data Engineer, Data Foundations | US Remote | 125000 | 156300 | 2026-11-04 | 224 | 30 |
| tala | Senior Data Engineer | US | 130000 | 200000 | 2026-11-04 | 11 | 2 |
| Machinify | Senior Data Engineer | Remote - US | 180000 | 220000 | 2026-11-03 | 61 | 8 |
| Glacier | Computer Vision DATA Engineer - Fully Remote | Remote Latin America based | 24000 | 42000 | 2026-11-03 | 4 | 0 |
Every row also has ats, board, id, department, workplaceType, employmentType, salaryMin, salaryMax,
salaryCurrency (ISO 4217), salaryPeriod, roleFamily, seniority, remote, daysSincePosted, url (the apply
link) and dataAsOf. All columns are flat, so the CSV or Excel export opens cleanly.
Input recipes
Remote jobs with a salary
{"keywords": ["python", "backend"], "remoteOnly": true, "hasSalary": true, "minSalary": 150000, "salaryCurrency": "USD", "sort": "salary"}
New today in one city
{"locations": ["London"], "firstSeenWithinDays": 1, "maxItems": 500}
One department across all companies
{"keywords": ["sales"], "keywordsInDepartment": true, "seniority": ["Senior", "Lead/Principal"]}
Lead list: companies hiring sales people this week (one row per company)
{"keywords": ["account executive", "sales development"], "firstSeenWithinDays": 7, "output": "companies", "maxItems": 200}
Real run, 5 Nov 2026 (with "excludeCompanies": ["jobgether"]): 776 matching sales roles first seen this week.
| company | matchingJobs | newMatchingJobs7d | companyOpenRoles | salaryAnnualMinUsd | salaryAnnualMaxUsd | topDepartments |
|---|---|---|---|---|---|---|
| bluelightconsulting | 203 | 203 | 815 | Sales & Marketing | ||
| Toast | 26 | 26 | 341 | 115000 | 237000 | Sales : Retail Sales AEs; Sales : Strategic Cuisines Sales AEs |
| Databricks | 19 | 19 | 927 | 272000 | 428450 | Enterprise Sales; Commercial & Mid-Market Sales |
| HubSpot | 18 | 18 | 106 | Sales |
Company rows also have ats, board, boardUrl (the careers page), remoteShare (0-1), topRoleFamily,
sampleTitles (up to 3), latestPostedAt and dataAsOf. Company rows count every matching posting.
Only some companies or platforms
{"companies": ["stripe", "notion", "ramp"], "ats": ["greenhouse", "ashby"]}
Closed-role history (time-to-fill)
{"keywords": ["data engineer"], "includeClosed": true, "closedWithinDays": 30, "maxItems": 200}
Set includeClosed: true to also return jobs that closed since tracking began. Closed rows carry closedOn (the day the job disappeared) and daysOpen (firstSeen to closedOn); open rows carry closedOn: null. Setting closedWithinDays: 30 keeps only jobs closed in the last 30 days, so the result is a clean time-to-fill sample without daily-expiry logic of your own.
Skip regions you don't hire in
{"keywords": ["python"], "remoteOnly": true, "excludeLocations": ["India", "LATAM"]}
Full posting text for a shortlist
{"keywords": ["data engineer"], "maxItems": 5, "includeDescription": true}
Each returned row then has non-empty descriptionText on reachable boards and descriptionSnippet for a quick scan. A company whose board is gone gives descriptionStatus: "unavailable" instead of failing the run.
Field reference (job rows)
| Field | Meaning |
|---|---|
company, ats, board, id | Company name, platform (greenhouse, lever, ashby), careers board token, the job's id on that board |
title, department, roleFamily, seniority | As posted; roleFamily and seniority are our classification of the title |
location, workplaceType, remote | Location text as the company wrote it; Remote/Hybrid/Onsite when the company says so (often empty); remote is true when either says remote |
employmentType | Full-time, Part-time, Contract, Internship, Temporary, when the company says so |
postedAt, daysSincePosted | The company's own posted (or last updated) date and its age in days. The most reliable freshness column |
firstSeen, trackedSince | First day the job appeared in our daily crawl; first day we crawled this company. Equal = it was already open when we started |
daysOpen, openSinceBeforeTracking | Days since firstSeen for jobs that opened after we started tracking the company, else empty + true. For closed jobs, daysOpen is firstSeen to closedOn |
closedOn | Day the job closed (disappeared from its board); null while open. Together with daysOpen, this is time-to-fill |
evergreen | Posted more than 180 days ago and still open |
salaryMin, salaryMax, salaryCurrency, salaryPeriod | The posted range as published (ISO 4217 currency) |
salaryAnnualMin, salaryAnnualMax | The same range as a yearly figure |
locationCount, otherLocations | How many locations this role is posted in, and every location besides location |
companyOpenRoles, companyNewRoles7d | The company's open jobs today, and how many of them first appeared in the last 7 days |
url, dataAsOf | Apply link; date of the snapshot the row came from |
descriptionText, descriptionSnippet, descriptionStatus | Only when includeDescription: true: full posting as plain text (up to 20000 chars), its first 280 chars, and ok or unavailable when that company's board could not be reached live. Off by default with no extra calls. |
Every run ends with two free rows: a status row (_status: ok or partial) and a summary row (matched, scanned,
returned, dataAsOf, the filters used, and for monitors newSinceLastRun). Filter them out with _status.
Aggregators are left out by default. A few boards (for example jobgether) re-post other companies' jobs by the
thousand, so they would crowd every "newest" search. Boards with over 1,000 open jobs, most of them new this week, are
recomputed daily and skipped; set "includeAggregators": true to get them back. excludeCompanies drops any other
board you don't want.
Only real openings. Talent pools, "general application" and "future opportunities" postings are left out by
default ("includeGeneralApplications": true brings them back, flagged generalApplication). When the keywords themselves
ask for them (for example "talent pool" or "general application"), they are included automatically. Salary figures that
cannot be real pay (a $0 range, "$19 a year") are dropped rather than shown wrong, and workplace type is only
Remote, Hybrid or Onsite.
Daily monitor (schedules)
Set onlyNewSinceLastRun: true and schedule the Actor daily. The first run saves a baseline, and every later run returns only
the matching jobs that were not there last time. A quiet day returns just the free summary row, so you pay only for new jobs.
Each distinct filter set keeps its own history, so you can run many monitors side by side. Connect the run to Slack, email,
Google Sheets or a webhook through Apify integrations.
Filters
Keywords (whole-word, any-of, title or title + department), exclude keywords, locations (any-of), exclude locations, exclude companies, remote only, workplace type,
employment type, role family, seniority, platform, company, has salary, minimum annual salary + currency, posted within N days,
first seen within N days, include recently closed jobs (includeClosed) with closedOn/daysOpen optionally limited to closures in the last N days (closedWithinDays),
sort by newest or highest salary, and max results. Every field is optional: an empty input returns
the newest 100 jobs.
Free preview (countOnly): set countOnly: true to scan and return only the summary (matched, scanned, dataAsOf) with 0 dataset items and no billing.
Pricing
$0.003 per row returned (a job, or a company row in lead-list mode). No start fee. The summary row is free, and quiet monitor days cost nothing. 1,000 jobs = $3.
FAQ
How fresh is the data? Every career site is crawled once a day (around 23:00 UTC). dataAsOf on every row shows the snapshot date.
It is not real-time: a job posted an hour ago appears the next day.
Do I get the job description? Not by default. Set includeDescription: true and each returned job row also carries descriptionText (full text), descriptionSnippet (first 280 chars) and descriptionStatus.
The text is fetched live from the company's public board for the rows you asked for, so keep maxItems small when you turn it on. If a board is down or moved, that row says unavailable and the run still succeeds.
Which companies are covered? 11,242 companies with a public Greenhouse, Lever or Ashby careers board, from startups to public companies. We add new boards every day.
Why are some salaries missing? Only companies that publish a pay range have one: 152,559 of 328,829 open jobs do.
Filter with hasSalary to keep only those.
Limits
- Greenhouse, Lever and Ashby only (no Workday, LinkedIn or Indeed).
- History starts on 31 Oct 2026, so
daysOpenis exact only for jobs that opened after that date. - Locations are the company's own text, matched as whole words: "US" matches "Austin, TX, US" but not "Russia"; "Berlin" matches "Berlin HQ".
Questions or a missing filter? Open an issue on the Actor's Issues tab. We read every one.
Use it from AI agents (MCP) and Python
AI agents. Add this Actor as a tool in Claude, Cursor, VS Code or any MCP client through the Apify MCP server. The agent reads the input schema, so a plain request is enough.
{"mcpServers": {"ats-jobs-search": {"url": "https://mcp.apify.com?tools=redomic/ats-jobs-search","headers": {"Authorization": "Bearer <YOUR_APIFY_TOKEN>"}}}}
Python. pip install apify-client, then:
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("redomic/ats-jobs-search").call(run_input={"keywords": ["engineer"], "maxItems": 20})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item)
More from us
- Ashby Jobs Scraper with Salaries: Ashby jobs scraper for any startup careers board (OpenAI, Ramp, Notion and thousands more), with salary ranges as numbers: min, max, currency, period, plus equity and bonus flags
- Google Jobs Scraper - Job Postings API: Google Jobs and job postings scraper: get job title, company, location, posted date, salary, full description and every apply link for any search
- Google Trends API: Trending Now & Interest Over Time: Trending-now searches and new-trends alerts/monitoring per country with the news behind them, plus interest over time, interest by region, and related and rising queries for any keyword
- Greenhouse Jobs Monitor & Scraper: Monitor Greenhouse jobs from any company careers board (Airbnb, Stripe, Discord and thousands more)
- Lever Jobs Scraper with Salaries: Lever jobs scraper for any company's careers page (Palantir, Spotify, Zoox, Shield AI and thousands more): flat rows with title, team, location, workplace, commitment, apply link, salary as numbers and the full description merged