ATS Jobs API - Greenhouse, Lever, Ashby, Workable | $1.50/1K avatar

ATS Jobs API - Greenhouse, Lever, Ashby, Workable | $1.50/1K

Pricing

$1.50 / 1,000 job returneds

Go to Apify Store
ATS Jobs API - Greenhouse, Lever, Ashby, Workable | $1.50/1K

ATS Jobs API - Greenhouse, Lever, Ashby, Workable | $1.50/1K

Give it company names, not board tokens. Finds each company's job board across 6 applicant tracking systems and returns every opening in one schema - normalised country, remote flag, salary. Pay per job; companies it cannot find are free.

Pricing

$1.50 / 1,000 job returneds

Rating

0.0

(0)

Developer

NorthWestSouth Data

NorthWestSouth Data

Maintained by Community

Actor stats

1

Bookmarked

2

Total users

1

Monthly active users

10 hours ago

Last modified

Share

ATS Job Scraper — company names in, jobs out

Every other job-board actor in this store wants a board token: greenhouse:gitlab, lever:spotify, ashby:ramp. That is backwards. You know the company. You do not know which HR software it happens to have bought.

Give this one company names or domains. It works out where their job board lives, reads it, and returns every opening in one schema.

{ "companies": ["Celonis", "SumUp", "raisin.com", "Delivery Hero"] }
Celonis → greenhouse:celonis 251 jobs
SumUp → greenhouse:sumup 370 jobs
raisin.com → greenhouse:raisin 35 jobs
Delivery Hero → smartrecruiters:deliveryhero 1056 jobs

No LinkedIn. No Indeed. No proxies, no browsers, no anti-bot arms race — only the public feeds these platforms publish so companies can embed their own openings on their own careers pages.

Systems covered

Found automatically: Greenhouse · Lever · Ashby · SmartRecruiters · Recruitee · Workable

On request only: Personio — see the honest note below.

How well the discovery actually works

Measured against 50 real DACH companies, names only, no tokens:

  • 29 of 50 (58%) resolved to a live board. Greenhouse 18, Ashby 4, SmartRecruiters 3, Recruitee 2, Lever 1, Workable 1.
  • The other 21 cost nothing and are listed with a reason in a separate dataset.

The 21 misses are companies whose board is on a system not covered here (Workday, SuccessFactors, softgarden, d.vinci), or whose board name differs from their brand name. For those, pass the board directly — greenhouse:acme always works and skips discovery entirely.

A board with zero open positions counts as not found. That is deliberate, and it is the single most important design decision in this actor. SmartRecruiters answers 200 OK with an empty list for any identifier, including invented ones. Workable is full of dormant trial accounts — zalando and flixbus both resolve there to a real but permanently empty board, while those companies actually hire somewhere else. Accepting an empty board would hand you a confident answer that yields no jobs, stop the search before the real board was found, and cache the wrong pairing for every later run. So empty means absent. The cost is that a company genuinely between postings reads as "not found" — free, honest, and overridable by naming the board yourself.

What you get per job

FieldExample
ats, companygreenhouse, celonis
titleAI & Management Consulting Intern (Value Engineering – DACH Market)
url, apply_urlDirect links to the posting and the application form
location, city, region, countryMunich, Germany → Munich / DE
remote, hybridFrom the platform's own flag where it exists, from the location text otherwise
department, teamEngineering / Platform
employment_typeFull-time · Part-time · Internship · Working student · Apprenticeship …
posted_at, updated_atISO 8601, whatever the source format was
salary_min, salary_max, salary_currencyWhere the platform publishes structured pay (Ashby, Recruitee)
description_html, description_textOptional — off by default, because it multiplies the output size
job_uidStable identity for deduplication across runs

Locations are normalised, so Berlin, München, Wien, Zürich and Remote Germany all resolve to a real ISO country code — you can filter on country instead of writing string matches. Salary is read only from structured fields; guessing a number out of prose produces wrong numbers, so it is not attempted.

Fair billing, by design

  • You pay per job returned. Nothing else.
  • A company that cannot be located is free. It goes to the ATS-COMPANIES-NOT-FOUND dataset with the reason.
  • A board that is found but unreadable is free.
  • maxJobs is a hard ceiling. Set it to 500 and you get at most 500 — the cap is claimed before each write, not after, so concurrent workers cannot overshoot it between them.
  • onlyNewJobs charges you once per posting, ever. Jobs returned by an earlier run are skipped. A daily schedule then pays only for genuinely new openings, which is what a job alert should cost.

The board directory grows as you use it

Every company resolved is remembered in a key-value store. The first run pays a handful of lookup requests; every run after that goes straight to the board. Re-running the same company list is fast and cheap, and the cache is yours.

Personio: the honest version

Personio is the standard applicant tracking system in the German Mittelstand, so it belongs here. It mostly does not work, and pretending otherwise would waste your money.

Tested against 15 real Personio boards: 3 answered, 10 returned a bot-protection challenge (a Vercel JavaScript checkpoint that replies 429 to anything without a browser), 2 did not exist. Getting past that would mean a headless browser and residential proxies — slower, far more expensive per job, and an explicit attempt to defeat a block the platform put there on purpose. This actor does not do that.

So Personio is never guessed. Name it and it will be tried: personio:orderbird, or by selecting it in atsPlatforms. If the checkpoint blocks it, you are told exactly that — not "company not found" — and you are not charged.

Useful setups

Daily alert for German engineering roles

{ "companies": ["Celonis", "SumUp", "N26", "HelloFresh", "Enpal"],
"countries": ["DE"], "titleKeywords": ["engineer", "entwickler"],
"onlyNewJobs": true }

Schedule it. You pay only for postings that appeared since yesterday.

Which of my target accounts are hiring right now?

{ "companies": ["forto.com", "sennder.com", "raisin.com"], "maxJobsPerCompany": 5 }

Everything a company has open, with full text

{ "companies": ["greenhouse:gitlab"], "includeDescription": true }

Why this data is fair to use

Each endpoint is the platform's own public job-board feed — no key, no login, no session. Their purpose is to let a company's openings be republished, which is exactly what happens here. robots.txt on these API hosts permits it. One request per company per run, and cached discovery keeps repeat runs to a single call.

Job postings are company data, not personal data. Recruiter names are not collected.

Limits worth knowing before you run it

  • Static feeds only. A company running its own JavaScript careers site with no ATS feed cannot be read, and is reported as a miss rather than guessed at.
  • Descriptions cost extra time. SmartRecruiters needs one additional request per job for them, capped at 200 per run.
  • Coverage is six systems. Workday and SuccessFactors are the big absentees; they need per-tenant handling and are not here yet. Say so in an issue if you need them.

Support

A company that should resolve but doesn't, or a field parsed wrongly? Open an issue — both count as bugs and get fixed.