ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API avatar

ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API

Pricing

$3.00 / 1,000 jobs

Go to Apify Store
ATS Jobs Search: Greenhouse, Lever & Ashby Jobs API

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

Redomic

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

13 hours ago

Last modified

Security

Limited permissions

Share

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

FieldWhat it tells you
salaryAnnualMin, salaryAnnualMaxPay 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
daysOpenDays 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
closedOnThe day a job disappeared from its board (null while open). With daysOpen, this is time-to-fill for roles that closed
companyOpenRolesHow many jobs this company has open right now, across all its roles
companyNewRoles7dHow many new roles the company opened in the last 7 days: a hiring-velocity signal for sales and recruiting
firstSeenThe day the job first appeared, even when the company never shows a posted date
locationCount, otherLocationsThe same role posted in many cities comes back once, with every location listed (and is billed once)
evergreenStill 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.

companytitlelocationsalaryAnnualMinsalaryAnnualMaxpostedAtcompanyOpenRolescompanyNewRoles7d
NateraSenior Data Engineer, Data FoundationsUS Remote1250001563002026-11-0422430
talaSenior Data EngineerUS1300002000002026-11-04112
MachinifySenior Data EngineerRemote - US1800002200002026-11-03618
GlacierComputer Vision DATA Engineer - Fully RemoteRemote Latin America based24000420002026-11-0340

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.

companymatchingJobsnewMatchingJobs7dcompanyOpenRolessalaryAnnualMinUsdsalaryAnnualMaxUsdtopDepartments
bluelightconsulting203203815Sales & Marketing
Toast2626341115000237000Sales : Retail Sales AEs; Sales : Strategic Cuisines Sales AEs
Databricks1919927272000428450Enterprise Sales; Commercial & Mid-Market Sales
HubSpot1818106Sales

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)

FieldMeaning
company, ats, board, idCompany name, platform (greenhouse, lever, ashby), careers board token, the job's id on that board
title, department, roleFamily, seniorityAs posted; roleFamily and seniority are our classification of the title
location, workplaceType, remoteLocation text as the company wrote it; Remote/Hybrid/Onsite when the company says so (often empty); remote is true when either says remote
employmentTypeFull-time, Part-time, Contract, Internship, Temporary, when the company says so
postedAt, daysSincePostedThe company's own posted (or last updated) date and its age in days. The most reliable freshness column
firstSeen, trackedSinceFirst day the job appeared in our daily crawl; first day we crawled this company. Equal = it was already open when we started
daysOpen, openSinceBeforeTrackingDays since firstSeen for jobs that opened after we started tracking the company, else empty + true. For closed jobs, daysOpen is firstSeen to closedOn
closedOnDay the job closed (disappeared from its board); null while open. Together with daysOpen, this is time-to-fill
evergreenPosted more than 180 days ago and still open
salaryMin, salaryMax, salaryCurrency, salaryPeriodThe posted range as published (ISO 4217 currency)
salaryAnnualMin, salaryAnnualMaxThe same range as a yearly figure
locationCount, otherLocationsHow many locations this role is posted in, and every location besides location
companyOpenRoles, companyNewRoles7dThe company's open jobs today, and how many of them first appeared in the last 7 days
url, dataAsOfApply link; date of the snapshot the row came from
descriptionText, descriptionSnippet, descriptionStatusOnly 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 daysOpen is 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 ApifyClient
client = 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