ATS Jobs Aggregator: Greenhouse, Lever, Ashby, SmartRecruiters avatar

ATS Jobs Aggregator: Greenhouse, Lever, Ashby, SmartRecruiters

Pricing

Pay per event

Go to Apify Store
ATS Jobs Aggregator: Greenhouse, Lever, Ashby, SmartRecruiters

ATS Jobs Aggregator: Greenhouse, Lever, Ashby, SmartRecruiters

Pricing

Pay per event

Rating

0.0

(0)

Developer

David-Solal Chalmeau

David-Solal Chalmeau

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

9 hours ago

Last modified

Categories

Share

ATS Jobs Aggregator: Greenhouse, Lever, Ashby & SmartRecruiters

Get every open job at companies you name, in one flat table, from each company's own public job-board API. Give it a list of companies (ashby:ashby, greenhouse:stripe, lever:ro, smartrecruiters:smartrecruiters) and get one row per job with title, department, location, remote flag, employment type, posting dates, apply URL and a plain-text description. Built for job aggregators, market research, competitor hiring tracking and LLM agents that need clean structured rows rather than scraped HTML.

What you get per job

FieldNotes
company, atsThe company you asked for and the ATS it came from
jobIdThe board's own job id (stable across runs)
title, department, locationDepartment and location are only as precise as the ATS provides
remotetrue / false / null. null means the ATS does not publish remote status (Greenhouse) — it is never guessed
employmentTypee.g. Full-time, FullTime. Only some ATS provide it (null otherwise)
postedAt, updatedAtISO 8601, or null when the ATS does not publish the field (Lever/Ashby/SmartRecruiters have no updatedAt; Greenhouse has both)
applyUrl, jobUrlDirect application link and job-page link
descriptionTextPlain text, HTML stripped, max 2000 characters. null for SmartRecruiters (its public list endpoint carries no description)
sourceUrl, fetchedAtThe exact API URL that produced the row, and when it was fetched

Example input

{
"companies": ["ashby:ashby", "greenhouse:stripe", "lever:ro", "smartrecruiters:smartrecruiters"],
"keywords": ["engineer"],
"locations": ["Berlin", "Remote"],
"remoteOnly": false,
"maxJobsPerCompany": 200,
"maxCompanies": 20
}

companies accepts "ats:slug" strings or {"ats": "greenhouse", "slug": "stripe"} objects. Keywords match the title or department (case-insensitive), locations match as substrings, and remoteOnly: true keeps only jobs the ATS explicitly marks remote.

Example output

Real rows from a run of the input above (descriptions truncated here for readability):

{
"company": "ashby",
"ats": "ashby",
"jobId": "7458d4e9-da2e-47bd-98cb-adfda43d42b2",
"title": "Engineering Manager - EU",
"department": "Engineering",
"location": "Remote - European Union",
"remote": true,
"employmentType": "FullTime",
"postedAt": "2024-03-04T14:29:08.532Z",
"updatedAt": null,
"applyUrl": "https://jobs.ashbyhq.com/ashby/7458d4e9-da2e-47bd-98cb-adfda43d42b2/application",
"jobUrl": "https://jobs.ashbyhq.com/ashby/7458d4e9-da2e-47bd-98cb-adfda43d42b2",
"descriptionText": "Hi 👋 I'm Colin https://uk.linkedin.com/in/colinhoweuk, Director of Engineering, Europe. How do you feel about software e...",
"sourceUrl": "https://api.ashbyhq.com/posting-api/job-board/ashby?includeCompensation=false",
"fetchedAt": "2026-10-28T05:26:19.043Z"
}
{
"company": "ro",
"ats": "lever",
"jobId": "3910baa9-f961-4380-ad0a-01deec07f7a2",
"title": "Analytics Engineer, Conversational Analytics",
"department": "Data",
"location": "New York, NY",
"remote": false,
"employmentType": "Full-time",
"postedAt": "2026-09-16T17:43:56.068Z",
"updatedAt": null,
"applyUrl": "https://jobs.lever.co/ro/3910baa9-f961-4380-ad0a-01deec07f7a2/apply",
"jobUrl": "https://jobs.lever.co/ro/3910baa9-f961-4380-ad0a-01deec07f7a2",
"descriptionText": "Join Tech @ Ro to build the future of healthcare, from the g...",
"sourceUrl": "https://api.lever.co/v0/postings/ro?mode=json",
"fetchedAt": "2026-10-28T05:26:19.065Z"
}

A company that cannot be fetched yields one row instead of jobs, and the run continues:

{
"company": "this-board-does-not-exist-xyz123",
"ats": "greenhouse",
"error": "BOARD_NOT_FOUND",
"message": "Greenhouse board not found: this-board-does-not-exist-xyz123"
}

error is BOARD_NOT_FOUND (no such board), UPSTREAM_ERROR (ATS returned an error or unusable payload) or INVALID_COMPANY (unknown ATS name or empty slug).

How to find a company's slug

Open the company's careers page and read the URL: boards.greenhouse.io/<slug>, jobs.lever.co/<slug>, jobs.ashbyhq.com/<slug>, jobs.smartrecruiters.com/<slug>. For companies that host the board on their own domain (e.g. Stripe's stripe.com/jobs), the slug is the Greenhouse/Lever identifier, usually visible in the embedded job-board iframe URL.

Pricing

Pay per event: a small start fee per run plus $0.0018 per delivered job row. Companies whose board is missing or fails, invalid company inputs, and jobs removed by your filters are free — you are only charged for rows you actually receive. If your spending limit is reached the Actor stops cleanly instead of continuing unpaid. Current prices are shown on this page.

Limits and honest notes

  • Sources: the official public job-board APIs of Greenhouse, Lever, Ashby and SmartRecruiters — the endpoints each vendor publishes for embedding a company's board on its own site. No login, no CAPTCHA or anti-bot bypass, no proxies.
  • Companies are user-supplied. The Actor only reads boards you name; it does not discover or crawl companies on its own.
  • No personal data beyond the posting. Rows contain only what the job posting publishes. No recruiter names, emails or phone numbers are extracted, even when a description mentions them.
  • Hard caps: at most 100 companies and 1000 jobs per company per run (defaults 20 and 200). For Greenhouse, Lever and Ashby the whole board arrives in one response, so the cap is applied after your filters and maxJobsPerCompany: 200 means at most 200 matching jobs. For SmartRecruiters the same cap also bounds how many postings are fetched while it paginates (100 per request), so a highly selective filter on a large SmartRecruiters board can return fewer rows than the cap — raise maxJobsPerCompany there if you need deeper coverage.
  • Field coverage differs by ATS. Greenhouse publishes no remote flag and no employment type, so those are null. Lever publishes no description HTML update time; Ashby and Lever publish no updatedAt. SmartRecruiters' public list endpoint has no description, so descriptionText is null there.
  • SmartRecruiters paginates 100 postings per request, up to your maxJobsPerCompany. Its unknown-company response is an empty list rather than an error, so a typo in a SmartRecruiters slug yields no rows and no error row.
  • Descriptions are truncated at 2000 characters to keep rows small; the full posting is always at jobUrl.
  • Politeness: boards are fetched with concurrency 3 and retries with exponential backoff on HTTP 429/5xx. Each board is fetched at most a handful of times per run (once, or one page per 100 postings for SmartRecruiters).
  • Listings change constantly; fetchedAt tells you exactly when a row was read.