Greenhouse, Lever, Ashby & Workable Jobs API – 4 ATSes
Pricing
from $1.50 / 1,000 job records
Greenhouse, Lever, Ashby & Workable Jobs API – 4 ATSes
Unified Career Site Job Listings API across Greenhouse, Lever, Ashby, SmartRecruiters & Recruitee — one feed, many ATS platforms. Filter by title, location or remote; dedup returns only new roles on scheduled runs. Pay-per-job. For recruiters & job boards.
Pricing
from $1.50 / 1,000 job records
Rating
0.0
(0)
Developer
K O
Maintained by CommunityActor stats
0
Bookmarked
3
Total users
2
Monthly active users
2 days ago
Last modified
Categories
Share
Job Postings Aggregator — Six ATS Platforms, One Schema
Covers six ATS platforms in one feed — Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable — twice the board coverage of the nearest combo-ATS listing on the Store (which covers three: Greenhouse, Lever and Ashby). Filters run before you're charged: titleIncludes, locationIncludes and remoteOnly are applied inside the fetch loop, before any record reaches the dataset or a billable event, so you only pay for postings that actually match.
Pain points
- Each ATS has its own API, its own field names, its own quirks — Lever hands you epoch milliseconds, Recruitee a non-standard timestamp, SmartRecruiters pages by offset and nests every value behind
{label}. Wiring up even three or four of these yourself is real integration work. - Tracking a target-company list across more than one ATS means running several separate scrapers and merging their output into one schema yourself.
- Filtering after the fact — pulling everything, then throwing away what you didn't want — means paying for records you never use.
- Watching a list of companies for genuinely new roles across multiple platforms means storing what you already pulled, per platform, and diffing every run yourself.
What we solve
- One schema, six ATS platforms. Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable all normalize to the same 12-field record — no per-platform integration work.
- Filters run before billing.
titleIncludes,locationIncludesandremoteOnlyare checked inside the fetch loop, before a record is normalized, pushed, or charged — postings that don't match never cost you anything. - Per-source failure isolation. A source that fails (bad slug, unreachable API) is skipped with a logged warning — the rest of your source list still comes back.
- Dedup built in, namespaced correctly.
onlyNewSinceLastRun(default on) tracks the last 20,000 ids seen, keyed byats:company:id— so the same numeric id from two different platforms, or two different companies, never collides or gets silently skipped.
Who uses it
Recruiters and sourcers tracking a list of target companies, niche and aggregator job boards, sales teams watching accounts for hiring signals, and labor-market/HR-tech products that need one consistent jobs schema instead of five or six different APIs.
Input
{"sources": ["greenhouse:stripe", "lever:ro", "ashby:Ramp"],"titleIncludes": ["engineer"],"locationIncludes": ["remote"],"remoteOnly": false}
| Field | What it does |
|---|---|
sources | List of "<ats>:<company>" entries. Supported ats: greenhouse, lever, ashby, smartrecruiters, recruitee, workable. The company is the slug from that ATS's careers URL. E.g. greenhouse:stripe, lever:ro, ashby:Ramp, workable:walter-careers. |
titleIncludes | Keep only jobs whose title contains one of these keywords (case-insensitive). Empty = all. Applied before billing. |
locationIncludes | Keep only jobs whose location contains one of these keywords. Empty = all. Applied before billing. |
remoteOnly | Keep only remote-flagged roles (or locations mentioning remote). Applied before billing. |
onlyNewSinceLastRun | Recommended for schedules — skips jobs already returned by a previous run, so you're only charged for genuinely new postings. Default true. |
maxItems | Stop after this many normalized records. |
Output
| Field | Description |
|---|---|
jobId | The posting's id in its source ATS. |
ats | Which platform this came from: greenhouse, lever, ashby, smartrecruiters, recruitee, or workable. |
company | The company/account slug you queried. |
title | Job title. |
location | Primary location, mapped from that ATS's own location shape. |
department | Department/team, mapped from that ATS's own tagging. |
employmentType | Employment type, mapped from that ATS's own field. |
remote | Boolean where the source ATS exposes one; null for ATSs (like Greenhouse) with no explicit remote flag. |
postedAt | Posting date, normalized to ISO 8601 regardless of the source's native format. |
url | Public posting URL. |
applyUrl | Direct apply-form URL, where the ATS separates it from the posting URL. |
source | Always "Jobs Aggregator". |
This actor has no bundled sample-run storage in this workspace to pull a record from directly, so — per this Actor's own documentation policy — here is a representative record, derived by tracing a genuine Ashby posting (the exact one shown in the Ashby Jobs Scraper README) through this actor's own field-mapping code, not a placeholder:
{"jobId": "34413f8d-26bf-4bbc-8ade-eb309a0e2245","ats": "ashby","company": "Ramp","title": " Security Engineer, Cloud","location": "New York, NY (HQ)","department": "Engineering","employmentType": "FullTime","remote": true,"postedAt": "2026-04-07T17:12:35.753+00:00","url": "https://jobs.ashbyhq.com/Ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245","applyUrl": "https://jobs.ashbyhq.com/Ramp/34413f8d-26bf-4bbc-8ade-eb309a0e2245/application","source": "Jobs Aggregator"}
Note what's missing next to the source-specific record: no compensationSummary (Ashby), no departments/offices array or requisitionId (Greenhouse), no workplaceType/allLocations/country (Lever), no requirementsHtml/benefitsHtml/countries (Workable). The unified schema trades platform-specific depth for one consistent shape across all six sources — see Which actor do I want? below if you need that depth back.
Which actor do I want?
- Tracking companies across more than one ATS, or don't want to run five separate scrapers? You're in the right place — this is the only actor in this family that covers all six platforms in one normalized feed.
- Need Greenhouse's multi-department/multi-office tagging or its internal requisition id? Use Greenhouse Jobs Scraper.
- Need Lever's remote/hybrid/onsite distinction, every location tag, or a country field? Use Lever Jobs Scraper.
- Need Ashby's published salary/compensation data? Use Ashby Jobs Scraper — this aggregator fetches Ashby's compensation payload too but drops the field to keep its schema consistent across all six sources.
- Need Workable's description/requirements/benefits split, or its deduplicated country array? Use Workable Jobs Scraper.
- Want the free CRM/Notion/HubSpot/Airtable/Supabase sync feature? It currently ships on the four single-board actors above (
syncEnabledinput), not yet on this one.
Pricing (Pay-Per-Event)
query— charged once per run for the poll across your sources.job-record— charged per normalized job pushed, after filtering. This is the primary event.apify-actor-start(Apify-managed) — covers baseline compute per run.
A daily monitor of a target-account list with a title filter returns just the handful of relevant new roles for pennies — and the filtered-out postings were never billed in the first place.
Finding company slugs
| ATS | Slug is the part of the careers URL |
|---|---|
| Greenhouse | job-boards.greenhouse.io/<slug> |
| Lever | jobs.lever.co/<slug> |
| Ashby | jobs.ashbyhq.com/<slug> |
| SmartRecruiters | jobs.smartrecruiters.com/<slug> |
| Recruitee | <slug>.recruitee.com |
| Workable | apply.workable.com/<slug> |
Source & reliability
All six sources are public ATS job-board APIs — no API keys, no proxies. A source that fails (bad slug, unreachable API) is skipped with a logged warning; the rest of your source list still comes back. SmartRecruiters sources page through up to 1,000 postings per company per run (10 pages × 100); the other five ATSs return each company's full board in a single call. Run npm test for the offline self-test covering the source parser and every ATS's field mapping.
FAQ
How am I charged?
A flat query event once per run, plus one job-record event per normalized job actually pushed — after your titleIncludes/locationIncludes/remoteOnly filters are applied. Postings your filters exclude are never normalized, pushed, or charged. With onlyNewSinceLastRun on (the default), a posting already returned in a previous run (tracked by ats:company:id, for the most recent 20,000 seen) is skipped and not re-charged.
Where does the data come from?
Six public ATS job-board APIs — Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable — the same data each platform's own hosted careers pages are built from. No API keys or proxies required.
How fresh is it?
Live at request time — there's no bundled or cached dataset behind this actor, it calls each source ATS directly on every run. Schedule it (daily or weekly) to keep catching new postings; onlyNewSinceLastRun means a recurring schedule only bills for roles you haven't seen yet.
Which actor do I want?
See Which actor do I want? above — short version: tracking multiple ATS platforms at once, stay here; need one platform's extra fields (salary, department/office arrays, workplace-type detail, or the description/requirements/benefits split), use that platform's single-board actor instead.
SEO keywords: jobs aggregator, multi ATS scraper, Greenhouse Lever Ashby scraper, job listings API, job postings API, new jobs feed, hiring signals, recruiting data, job board aggregator, ATS jobs feed