ATS API — Job Board, Job Listings & Applicant Tracking | $3/1K
Pricing
from $3.00 / 1,000 job listings
ATS API — Job Board, Job Listings & Applicant Tracking | $3/1K
Unofficial — not affiliated with any ATS vendor. ATS aggregator and job board API: give company names, domains or careers page URLs, it detects the applicant tracking system (Greenhouse, Lever, Ashby, Workday, Workable, Personio, Rippling) and normalizes every open role into one schema.
Pricing
from $3.00 / 1,000 job listings
Rating
0.0
(0)
Developer
KENKO
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
17 hours ago
Last modified
Categories
Share
ATS Jobs Scraper — Greenhouse, Lever, Ashby, Workday | $3/1K
Unofficial. This Actor is not affiliated with, endorsed by, or sponsored by Greenhouse, Lever, Ashby, Workday, Workable, Personio or Rippling. All product names and trademarks belong to their respective owners and are used here only to describe which job boards this Actor can read. It reads each vendor's own public feed, subject to that vendor's
robots.txt.
A job listings API for company career pages. Give it company names. Get back every open role, normalized.
{ "companies": ["stripe", "linear.app", "https://jobs.lever.co/spotify"] }
You do not have to know which applicant-tracking system a company uses. The Actor works it out, reads the board, and returns one row shape no matter how many different systems a run touched.
Use it as a Greenhouse job board API, a Lever jobs API, an Ashby jobs API, a Workday job board API or a Workable jobs API — or point it at a mixed list and let it sort out which is which.
Why this exists
Job data on the market is scraped HTML. That breaks every time a career page is redesigned, and it needs proxies and anti-bot handling to collect at all.
This reads the JSON and XML feeds the ATS vendors publish themselves —
boards-api.greenhouse.io, api.lever.co, api.ashbyhq.com and four more.
Nothing here logs in, uses a proxy, solves a challenge, spoofs a user agent, or
parses a layout. The user agent is atsfeed/1.0 and says where it came from.
Six of the seven are documented, unauthenticated vendor endpoints. Workday is the exception and is labelled as one: it is an undocumented career-site endpoint, read from a career-site URL you supply, not a published API. It is included because it is where a large share of enterprise roles actually live — but you should know which of these you are depending on.
What it will not read
Every host is checked against its own robots.txt before the first request, and
a published Crawl-delay sets the spacing. If a vendor changes its mind about
who may read a feed, this Actor stops on its own rather than waiting for someone
to notice.
That check is why two systems are not supported:
- SmartRecruiters —
api.smartrecruiters.com/robots.txtallows exactly one agent,LinkedInBot, and disallows everything else. We are everything else. - Breezy — its
/jsonendpoint is undocumented and its terms speak against automated collection.
Requests are also capped per host — at most 4 in flight and 5 per second, and half that into a single Workday tenant. A whole 2,000-role Workday board takes about 2½ minutes rather than 8 seconds. That is deliberate: a job feed that gets its source annoyed is worth nothing next month.
Supported systems
| ATS | Addressed by | Descriptions | Endpoint |
|---|---|---|---|
| Greenhouse | slug, boards.greenhouse.io/… | yes | documented |
| Lever | slug, jobs.lever.co/… | yes | documented |
| Ashby | slug, jobs.ashbyhq.com/… | yes | documented |
| Workable | slug, apply.workable.com/… | yes | documented |
| Personio | slug, *.jobs.personio.de | yes | documented |
| Rippling | slug, ats.rippling.com/… | — | documented |
| Workday | full careers URL (*.myworkdayjobs.com/…) | — | undocumented |
Workday is addressed by URL rather than name because its host encodes the data centre and its path encodes both tenant and site — none of which can be derived from a company name.
Input
Everything but companies is optional.
| Field | Meaning |
|---|---|
companies | Names, domains, board URLs, or provider:slug. |
keywords / excludeKeywords | Title filters. Whole-word, so go does not match Google. Multi-word entries match as phrases. |
locations / countries / departments | Further filters. countries takes ISO-2 codes. |
remoteOnly | Remote only. Hybrid is excluded, and so are roles the board says nothing about. |
postedWithinDays | Recency. Undated roles are excluded — they cannot be shown to be recent. |
searchDescriptions | Match keywords against the body text too. |
includeDescription / includeDescriptionHtml | Add the description as plain text and/or original HTML. |
maxJobsPerCompany / maxJobsTotal | Cost ceilings. Large Workday tenants list 20,000+ roles. |
Output
One row per role:
provider company companySlug jobId title department teamemploymentType location locations[] country workplaceType isRemotepostedAt updatedAt salaryText salaryMin salaryMax salaryCurrencysalaryPeriod url applyUrl description descriptionHtml scrapedAt
Measured coverage over 1,287 live roles from 11 companies across all 7 systems:
| Field | Present |
|---|---|
title, url, location | 100% |
country | 99.3% |
postedAt | 88.7% |
department | 77.0% |
workplaceType | 49.6% |
employmentType | 41.6% |
salaryMin | 13.1% |
The lower rows are not gaps in this Actor — they are fields the boards
themselves leave blank. Rippling publishes no dates at all; most companies
publish no pay. A field is null when the source did not say. Nothing is
inferred to fill a column, because a guessed salary is worse than an empty one.
department is 100% on every system except Workday, which drags the average
down on its own. Workday postings carry no category at all, only a
jobFamilyGroup search facet. Taking a whole Workday board fills
department for 100% of its rows by replaying the search once per category —
NVIDIA's 2,000 postings, fully attributed. Taking a slice does not, because
labelling even 300 rows means sweeping all 2,617 postings, and the run log says
so out loud when it declines.
The 0.7% of rows with no country are rows whose location names no place:
"Remote", "N/A", "LOCATION".
Four judgement calls worth knowing about:
workplaceTypeisnull, not"onsite", when a board is silent. Silence is not evidence of an office.- A role open in several places is
"remote"if any one of those places reads remote. The order a board lists its offices in is its ordering, not a statement about the role, so reading only the first would decideremoteOnlyat random. - A bare two-letter code in a location is read as a US state (
Austin, TX→ US) because US boards writeCity, STconstantly while non-US boards spell the country out (Berlin, Germany). SoBerlin, DEresolves to US — spell the country out and it resolves correctly. - A city with one dominant reading resolves its own country (
London→ GB,Bengaluru→ IN). This is only consulted after subdivision codes, so the US homonyms still win where a board qualifies them:London, KY→ US.
Pricing
Pay per job returned: $3 per 1,000 roles, flat — the same rate on every
plan, with no volume tier that quietly makes the number in the title wrong for
whichever tier you happen to be on. Plus a $0.005 run start fee. maxJobsTotal
is a hard ceiling, so a run cannot cost more than you allowed it to — including
after a platform migration mid-run.
Notes
- De-duplication: companies commonly run two boards at once (a Greenhouse board and a Workday mirror). The same role from both collapses to one row.
- Missing companies: if a company self-hosts its careers page or uses an ATS
not listed above, the run reports it under
SUMMARY.failuresrather than failing. Pass a board URL directly if auto-detection misses it. - Moved boards: a slug whose board has been closed usually redirects to the vendor's marketing site. That is reported as a miss, not retried.
- Resumable: progress is checkpointed, so a migrated run neither re-fetches nor re-charges for boards already delivered.
- Downstream use:
apply.workable.compublishes. It does not restrict this Actor, but it is a stated preference about what may be done with the rows afterwards, and you should know it exists.Content-Signal: ai-train=no
Common questions
How do I scrape company career pages without breaking every month? Don't parse the page. Every system here publishes a machine-readable feed behind the careers page, and that feed changes far less often than the design does. This Actor reads the feed.
Is there a free job board API?
The vendor feeds are free and unauthenticated — you can call
boards-api.greenhouse.io yourself. What you pay for here is the part that is
tedious rather than hard: working out which of seven applicant tracking systems
a company is on, addressing each one correctly, obeying seven different
robots.txt files and rate limits, and flattening seven incompatible payloads
into one row shape with real country and salary parsing.
Can I get a job posting API across many companies at once?
Yes — pass a list. Boards are fetched concurrently within the per-host limits,
duplicates across a company's two boards collapse to one row, and
maxJobsTotal caps what the run can cost you.
Which applicant tracking system API does a given company use?
Pass the company name or domain and read the provider column. Detection is the
first thing the run does, and it is reported per company in SUMMARY.
Development
npm installnpm test # 66 tests, no networknpm run demo # live run against real boards