Greenhouse, Lever, Ashby & Workday Jobs: Careers Page Scraper
Pricing
from $1.60 / 1,000 job returneds
Greenhouse, Lever, Ashby & Workday Jobs: Careers Page Scraper
Greenhouse, Lever, Ashby & Workday jobs API: filter by title, location, remote and posting date before you pay. Also Workable, SmartRecruiters and Recruitee.
Pricing
from $1.60 / 1,000 job returneds
Rating
0.0
(0)
Developer
Your Evenings
Maintained by CommunityActor stats
0
Bookmarked
2
Total users
1
Monthly active users
23 minutes ago
Last modified
Categories
Share
Why this one
- Filters that actually apply, before you're charged. Filter by title keywords (and excludes), location, remote, department and posted date. Jobs your filters remove are never returned or charged, and each company's row shows how many were filtered out. Matching ignores accents, handles German compound titles ("entwickler" finds "Softwareentwickler") and knows local place names and remote words (München = Munich, Homeoffice = remote).
- Workday career sites too, including boards with more than 2,000 jobs. Give a company name, a domain or a
myworkdayjobs.comlink. It reads the career site's own public job search and works around Workday's 2,000-results-per-search limit; if any jobs can't be read, the company's note says how many and why. - Live from each job board, not a stale daily copy. Every run reads each company's board directly, so you get the jobs it lists at the moment of the run.
- Every company you enter gets a status, and you can see the board's full size. The
COMPANY-STATUSCSV has one line per input, including repeats and companies not reached, with its status, the board's open-job count, jobs returned, jobs filtered out and a note. Every job row carriescompanyTotalJobs. If a board token you gave has moved to another supported job board, the jobs are read from the new board and the status saysboard_moved. Companies we can't find are free. - Your limits are honoured, with no hidden extra runs or double charges.
maxJobsPerCompanycaps rows per company in normal mode, charging stops at your maximum cost per run, one run never starts other runs, and two inputs that point to the same board are read and charged once (the second gets a freeduplicaterow). - Alerts for new and removed jobs. Turn on
monitorModeand schedule it daily: you get only jobs opened or closed since the last run, withfirstSeenAtandlastSeenAt. - No AI-guessed fields. Salary and workplace type are copied from the board's own fields, and salary is filled only when the employer posts it.
Greenhouse, Lever, Ashby & Workday Jobs API: Careers Page Scraper
Works with: Greenhouse · Lever · Ashby · Workday · Workable · SmartRecruiters · Recruitee · Personio · Teamtailor
Runs on
Apify. Use it from Make, Zapier,
n8n or the Apify API.
Greenhouse, Lever, Ashby & Workday Jobs API turns a list of company domains into a clean, up-to-date list of their open jobs. Give it stripe.com, a careers page URL or a job-board link. It finds the company's applicant tracking system (ATS) and reads every open job from the ATS's public job-board API (for Workday, the career site's own public job search), then returns one normalised row per job: title, department, location, remote flag, employment type, salary (when the employer posts it), job URL, apply URL and dates.
One Actor reads the public job boards of exactly these nine applicant tracking systems:
| ATS | Typical board URL | Notes |
|---|---|---|
| Greenhouse | boards.greenhouse.io/{token}, job-boards.greenhouse.io/{token} | Posted pay ranges included |
| Lever | jobs.lever.co/{token} (and the EU instance jobs.eu.lever.co) | Posted salary range included |
| Ashby | jobs.ashbyhq.com/{token} | Posted compensation included |
| Workable | apply.workable.com/{token} | |
| SmartRecruiters | jobs.smartrecruiters.com/{token} | |
| Recruitee | {token}.recruitee.com | Posted salary included |
| Workday | {tenant}.wd{N}.myworkdayjobs.com/{site}, wd{N}.myworkdaysite.com/recruiting/{tenant}/{site} | Department from the job family. Location shows "3 Locations" for multi-location jobs unless a location or remote filter is set (then each job's page is read). Posted date for the last 30 days. No salary fields |
| Personio | {token}.jobs.personio.de (or .com) | Only when the employer has switched on Personio's public XML job feed (see below). Posted salary included |
| Teamtailor | {token}.teamtailor.com, or the employer's own career-site domain (e.g. jobs.tibber.com) | Read from the career site's public RSS job feed (see below). No salary, employment type or update date in the feed |
Not covered yet: BambooHR, iCIMS, SuccessFactors, Taleo, Jobvite and companies' own in-house careers sites. Companies on those systems are returned as not_found (free of charge).
Use it as a Greenhouse jobs API, a Lever jobs scraper, an Ashby jobs API or a Workday jobs scraper without building separate integrations, or as a careers page jobs feed for a list of target accounts.
What you can use it for
- Hiring signals for sales and recruiting teams. Turn on monitor mode and schedule it daily: you get only the jobs that were opened or closed since the last run.
- Job boards and aggregators. Pull fresh jobs straight from employers' own boards in one schema.
- Market and salary research. Compare roles, locations, remote share and posted pay ranges across companies.
- Talent intelligence. See which teams a company is growing, and where.
Example tasks (ready-made inputs)
Open one, click Try for free, then swap in your own companies:
- Track open jobs at top AI startups
- Export Greenhouse job boards to CSV or JSON
- Collect posted salary ranges from tech job boards
- Daily hiring alerts for your target accounts
- Find open jobs at UK and European fintechs
- Export Workday jobs to CSV or JSON
How it finds each company's jobs
For every line of input the Actor:
- Uses the board directly if you give an explicit token (
greenhouse:stripe) or a job-board URL (https://jobs.lever.co/spotify). If that board no longer exists or lists no jobs, the same token is tried on the other supported job boards (see Moved boards). - Otherwise derives likely board tokens from the domain (for example
figma.com→figma) and checks them against each ATS's public API. Boards whose company name or job links clearly belong to a different organisation are skipped. - If that fails, reads up to 4 pages of the company's website (your careers URL,
/careers,/jobsand the homepage) and looks for links to a supported job board, including Workday career sites. - If that fails too, checks whether Workday has a tenant with that name: each Workday host's public
robots.txtsays whether the tenant exists and lists its career sites. The main external site (the one with the most jobs, skipping intern, campus and internal sites) is used. - If nothing is found, returns one row with
status: "not_found". Not-found companies are free.
Each row says how its board was found (detectionMethod) and how sure the Actor is that the board is the right company (detectionConfidence):
- high: you gave the token or board URL; the company's website links to the board; the board's job links are on the company's own domain; or the board's company name matches the domain exactly.
- medium: a token guessed from the domain answered on Lever, Ashby or Workday. These boards publish no company name to cross-check, so verify them once.
- low: the board's company name only partly matches the domain. Check these before relying on them. For the most reliable runs, pass the board token or board URL once you know it; the
boardTokenfield in the output gives you the value to reuse.
Input
| Field | What it does | Default |
|---|---|---|
companies | Domains, careers URLs, job-board URLs or ats:token values, one per line | 5 example companies |
includeDescription | Adds a plain-text descriptionText field (emails and phone numbers removed) | off |
maxJobsPerCompany | Caps rows per company (0 = all jobs), applied after the filters below | 0 |
titleKeywords | Keep jobs whose title contains any of these words or phrases | none |
excludeTitleKeywords | Drop jobs whose title contains any of these words or phrases | none |
locations | Keep jobs whose location contains any of these places | none |
remoteOnly | Keep only remote jobs | off |
departments | Keep jobs whose department or team contains any of these texts | none |
postedWithinDays | Keep jobs posted within the last N days (0 = any date) | 0 |
keepJobsWithoutPostedDate | With postedWithinDays set, keep jobs whose board gives no posted date | on |
monitorMode | Return only new and removed jobs since the previous run | off |
emitBaselineOnFirstRun | In monitor mode, return all current jobs on the first run | on |
stateStoreName | Named key-value store that remembers seen jobs | careers-jobs-api-state |
persistState | Keep firstSeenAt accurate across normal runs | on |
scanCareersPage | Look for job-board links on the company website if guessing fails | on |
maxConcurrency | Max parallel HTTP requests | 5 |
requestTimeoutSecs | Per-request timeout; failed requests are retried 3 times with backoff | 15 |
Example input:
{"companies": ["figma.com","https://www.notion.so/careers","https://jobs.lever.co/spotify","greenhouse:stripe","ashby:ramp"],"includeDescription": false,"monitorMode": false}
Accepted explicit prefixes: greenhouse:, lever:, lever-eu:, ashby:, workable:, smartrecruiters:, recruitee:, personio:, workday:, teamtailor:.
Job filters (applied before you're charged)
The Actor reads each board in full, applies your filters, and only then pushes and charges job rows. Jobs a filter removes are never returned or charged. All filters are optional and combine with AND; values inside one filter combine with OR.
{"companies": ["stripe.com", "figma.com"],"titleKeywords": ["engineer", "engineering"],"excludeTitleKeywords": ["intern"],"locations": ["London", "Remote"],"postedWithinDays": 7}
How each filter matches:
titleKeywords/excludeTitleKeywords: whole words or phrases in the job title, ignoring case and accents (developpeurmatches "Développeur").engineermatches "Software Engineer" but not "Engineering Manager", so list both forms if you want both. A single word of 5 or more letters also matches at the end of a compound word and with the German endings -in/-innen:entwicklermatches "Softwareentwickler (m/w/d)" and "Entwicklerin", andberatermatches "Steuerberater". It doesn't match at the start of a word, sojavadoesn't match "JavaScript". There's no translation:developerdoesn't match "Entwickler".locations: whole words in the board's location text, ignoring case and accents (Zurichmatches "Zürich"). About 50 groups of place names are matched together: local and English names (München/Munich, Köln/Cologne, Wien/Vienna, Warszawa/Warsaw, Lisboa/Lisbon, Deutschland/Germany, Schweiz/Suisse/Switzerland and others), short forms (NYC/New York, UK/United Kingdom/England/Scotland/Wales/Northern Ireland, USA/US/United States, UAE, SF/San Francisco) and old names (Bangalore/Bengaluru, Bombay/Mumbai). A city isn't matched to its country, soUnited Kingdomdoes not match a job listed only as "London".Remotealso matches jobs the board flags as remote.remoteOnly: keeps jobs withisRemote: trueorworkplaceType: "remote". Hybrid jobs are not included. Remote words in other languages count when they're in the location or the board's workplace field: Homeoffice, mobiles Arbeiten, ortsunabhängig, télétravail, teletrabajo, remoto, teletrabalho, thuiswerk, telelavoro, smart working, praca zdalna, på distans, etätyö and similar. Text that also says hybrid stays hybrid.departments: case- and accent-insensitive partial match on the board's department or team name (engmatches "Engineering"). Department names are whatever each employer uses.postedWithinDays: compares the board'spostedAtwith the run time, so a scheduled run always looks at the latest days.
Missing fields. If a filter needs a field the board doesn't give for a job: with locations set, jobs with no location are dropped; with departments set, jobs with no department or team are dropped; with postedWithinDays set, jobs with no posted date are kept and flagged postedAtUnknown: true, unless you turn off keepJobsWithoutPostedDate.
What you see. Every job row has companyTotalJobs (open jobs on the board before filters and limits). When any filter is set, each company also gets one free company row with companyTotalJobs, filteredOut and jobsReturned. If nothing matches, the company row has status: "no_matching_jobs" and a note with the board's job count. SUMMARY shows the filters used and the total filtered out.
In monitor mode the filters apply to new and removed jobs: only matching changes are returned and charged. Changes your filters exclude are recorded, so they aren't reported later either.
Output
One row per job. Example (Greenhouse):
{"recordType": "job","status": "ok","changeType": null,"company": "Figma","companyDomain": "figma.com","ats": "greenhouse","boardToken": "figma","detectionMethod": "token-guess","detectionConfidence": "high","jobId": "5426468004","title": "Account Executive, Enterprise","department": "Sales","team": null,"location": "San Francisco, CA • New York, NY • United States","isRemote": false,"workplaceType": null,"employmentType": null,"salaryMin": 165000,"salaryMax": 190000,"salaryCurrency": "USD","salaryPeriod": "year","salaryText": "Annual Base Salary Range: USD 165,000 - USD 190,000","url": "https://boards.greenhouse.io/figma/jobs/5426468004?gh_jid=5426468004","applyUrl": "https://boards.greenhouse.io/figma/jobs/5426468004?gh_jid=5426468004","postedAt": "2025-01-28T23:57:29.000Z","postedAtUnknown": false,"postedAtBasis": "board-date","companyTotalJobs": 139,"updatedAt": "2026-07-22T09:37:08.000Z","firstSeenAt": "2026-10-21T17:04:19.642Z","lastSeenAt": "2026-10-21T17:04:19.642Z","input": "figma.com","note": null}
Field notes:
- Salary fields are filled only when the employer publishes pay on its board. Nothing is estimated. Where an employer posts several ranges (for example by pay zone),
salaryMinandsalaryMaxspan them andsalaryTextlists each one. isRemoteistruewhen the board marks the job remote, a listed location says Remote, or the location uses a local remote word such as Homeoffice or télétravail (not when it also says hybrid).workplaceTypeisremote,hybridoronsitewhen the board says so.- Dates are ISO 8601 in UTC. Not every ATS publishes an update date, so
updatedAtcan be null. postedAtUnknownistruewhen the board gives no posted date for the job.postedAtis the board's own posting date (for Greenhousefirst_published, neverupdated_at, which Greenhouse changes across whole boards at once).postedAtBasissays where it came from:board-date,personio-created-at(the job's creation date in Personio),teamtailor-published(the publication date in the Teamtailor feed), orapproximate-from-listing-textfor Workday jobs whose listing only says "Posted 3 Days Ago" (converted to a UTC date, accurate to about a day;postedWithinDaysallows one extra day for these). Workday jobs listed as "Posted 30+ Days Ago" have nopostedAtunless their job page is read.companyTotalJobsis the number of open jobs the company's board lists at run time, before your filters andmaxJobsPerCompany. It is on every job row and on company rows for boards that were read (null fornot_found,duplicateanderror). Compare it with the rows you got to check nothing was left out. For SmartRecruiters it is the board's owntotalFoundcount; the Actor reads at most 10,000 jobs from one SmartRecruiters board.- Company rows. Inputs that don't produce jobs return one row with
recordType: "company"and astatusofnot_found,no_open_jobs,no_matching_jobs(filters set, nothing matched),no_change,partial,empty_unconfirmedorfetch_failed(monitor mode, see Monitor mode),baseline_saved,duplicate,feed_disabled(Personio career page found but its public job feed is switched off) orerror, plus anoteexplaining why. A board token you gave that was found on a different job board gets aboard_movedrow withfromAts,toAtsandfromBoardToken(see Moved boards). When job filters are set, companies with matching jobs also get a company row (statusok,changesorpartial_budget) withcompanyTotalJobs,filteredOutandjobsReturned. Company rows are never charged. - No personal contact data. The Actor never outputs recruiter or hiring-manager names or contact details, and removes email addresses and phone numbers from description text.
The Output tab has four views: Jobs, Salaries, Monitor changes and Detection. A run summary (status per company, detected board, timings) is saved as SUMMARY in the run's key-value store.
Per-company status: COMPANY-STATUS CSV
Every run also saves COMPANY-STATUS, a CSV in the run's key-value store (linked from the Output tab and from the run's final status message). It has one line per company you entered, in your input order:
| Column | Meaning |
|---|---|
input | The line you entered |
company, ats, boardToken | The board it resolved to (empty if not found) |
status | ok, board_moved, partial_budget, no_open_jobs, no_matching_jobs, no_change, changes, partial, empty_unconfirmed, fetch_failed, baseline_saved, not_found, feed_disabled, duplicate, error or skipped_budget |
totalJobs | Open jobs on the board before filters and limits (empty when the board wasn't read) |
returned | Job rows returned for this input |
filteredOut | Jobs (or monitor changes) your filters excluded |
note | Plain-English explanation |
fromAts, toAts | For board_moved lines: the job board you gave and the one the jobs were read from (empty otherwise) |
Exact repeats in your input are read once and listed as duplicate. Companies the run didn't reach because it hit your maximum cost are listed as skipped_budget. Neither is charged.
Workday career sites
Give a company name (Mastercard), a domain (crowdstrike.com), a career-site link (https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite) or an explicit token (workday:adobe.wd5/external_experienced, or just workday:intel to find the host and site). The boardToken in the output (tenant.wdN/site) is the exact value to reuse.
Jobs are read from the public job search the career site itself uses (/wday/cxs/{tenant}/{site}/jobs), with no login and no candidate data. Requests go one at a time per Workday site with a short gap, back off when the site answers HTTP 429, and respect the site's robots.txt (sites it disallows are skipped and returned as not_found).
Boards with more than 2,000 jobs. One Workday search returns at most 2,000 results, 20 at a time; later pages repeat the first page. The Actor splits the search by job family (and, when needed, by other filters the site offers, such as time type or location) so each part stays under 2,000, then merges the results by job ID. The board's true total comes from Workday's own filter counts, and companyTotalJobs reports it. In our tests (22 Oct 2026) all of NVIDIA's roughly 2,700 open jobs were read (about 150 requests, 2.5 minutes). If a board changes while it's being read, a second pass picks up jobs that moved between pages. If some jobs still can't be read, or the run is about to time out, the company row and COMPANY-STATUS note say how many of the total were read and why.
What Workday rows contain. department comes from the job family. For a job listed in several places, location shows the count (for example "3 Locations") unless you set a locations filter or remoteOnly, in which case that job's own page is read to get every location. postedAt is filled for jobs posted in the last 30 days (Workday's listing shows "Posted 30+ Days Ago" for older ones). With postedWithinDays above 30, older jobs' pages are read for the exact date. includeDescription reads each job's page for the full text, which is slower on big boards. Workday shows no salary fields in its search, so salary is empty.
Personio career pages
Give a company name (thermondo), a domain (thermondo.de), a career-page link (https://mway.jobs.personio.de) or an explicit token (personio:mway).
Jobs are read from the employer's public Personio XML job feed (https://{token}.jobs.personio.de/xml, or .jobs.personio.com), the feed Personio offers for job boards and websites. No login, no candidate data, and no scraping of the career page's HTML. Employers can switch this feed off in Personio. When it is off, the jobs can't be read:
- If you gave a Personio token or link, or the company's website links to its Personio page, you get one free row with
status: "feed_disabled"and a note saying the career page exists but its public feed is switched off. - If the Personio page was only a guess from a name or domain, you get a free
not_foundrow whose note mentions the Personio page with the feed switched off. - Unknown Personio names return a free
not_foundrow.
Requests to Personio go one at a time with a short gap, and each career site's robots.txt is respected.
What Personio rows contain. department and team (Personio's recruiting category) as published; location is the main office plus any additional offices, separated by "; "; employmentType combines Personio's type and schedule (for example Full-time, Part-time, Internship, Working student, Trainee, Contract); salary only when the employer adds it to the feed; url and applyUrl are the job's public Personio page. postedAt is the job's creation date in Personio (postedAtBasis: "personio-created-at"), which can be earlier than the date it was first published. includeDescription adds the description sections from the feed.
Teamtailor career sites
Give a company name (Oatly), a domain (tibber.com), a career-site link (https://polestar.teamtailor.com/jobs) or an explicit token: teamtailor:polestar, or the career site's own host for sites on the employer's domain (teamtailor:jobs.tibber.com).
Jobs are read from the career site's public RSS job feed ({career site}/jobs.rss), which Teamtailor documents for sharing a career site's public jobs with other systems. No login, no API key and no scraping of the career pages. The feed is paged 100 jobs at a time, so career sites with up to 5,000 open jobs are read in full. Requests go one at a time per career site with a short gap, and each site's robots.txt is respected. A career site on the employer's own domain is found when the company's careers page is (or redirects to) a Teamtailor-built site.
What Teamtailor rows contain. title; department; team (Teamtailor's division, often empty); location as city and country for each listed location, separated by "; "; workplaceType from Teamtailor's remote status (fully remote = remote, hybrid = hybrid, none = onsite; "temporarily remote" is left empty); url and applyUrl are the job's page on the career site; postedAt is the publication date in the feed (postedAtBasis: "teamtailor-published"); includeDescription adds the job description. company is the career site's name as the feed gives it (for example "Oatly AB").
What Teamtailor's feed doesn't have: salary, employment type (full-time, part-time and so on), an update date (updatedAt is empty) and a separate apply link. Those fields are always empty for Teamtailor jobs. Office street addresses in the feed are not copied.
Moved boards
Companies sometimes switch job boards (for example from Lever to Ashby) and keep the same name in the URL. When you give an explicit token (lever:notion) or a board URL (https://jobs.lever.co/notion) and that board answers "not found" or lists no open jobs, the Actor tries the same token on the other supported public job-board feeds: Greenhouse, Lever (US and EU), Ashby, Workable, SmartRecruiters, Recruitee, Personio and Teamtailor.
- Found with open jobs: the jobs are read from the new board, with your filters applied before charging and charged as usual. The company gets one free row with
status: "board_moved",fromAts(the board you gave),toAts(where the jobs came from),fromBoardTokenand a note. Job rows show the new board inatsanddetectionMethod: "moved-board". Use the newatsandboardTokenin future runs. - Not found anywhere: you get the same free
not_foundrow as before, and the note lists the job boards that were checked. - The old board still exists but is empty, and nothing is found elsewhere: you get
no_open_jobsas before. - A board under the same token that belongs to a different company (its company name or job links don't match) is not used. On Workable, SmartRecruiters, Recruitee, Personio and Teamtailor, where short names are reused more often, a board is used only when its company name matches the token.
- Workday is not searched, because a token alone doesn't say which Workday host a company would be on. A Workday token that's gone (
workday:tenant.wd5/site) is tried on the other boards using the tenant name. - This applies only to tokens and board URLs you give. Domains and company names are already looked up on every supported job board.
- The lookup makes a request or two to each job board's public API, at the normal rate, and isn't charged.
- In monitor mode, the first run after a move saves the new board as the baseline (job IDs differ between job boards, so the old board's history can't be carried over).
Monitor mode: only new and removed jobs
Turn on monitorMode and schedule the Actor (daily or weekly) with the same input:
- The first run for a company saves its current jobs as a baseline and, by default, returns them all with
changeType: "new". - Later runs return only jobs that appeared (
changeType: "new") or disappeared (changeType: "removed") since the previous run. Removed rows keep the job's title, location, URL and first/last-seen dates. - A company with no changes returns one
no_changerow, charged at the low monitor-check price.
When a board can't be read in full. The saved job list is only replaced after a complete read of the board:
- Read failed (for example the job board returned an error): the company gets a free
fetch_failedrow, the saved list is left as it was, and no jobs are reported as removed. The board is checked again on the next run. - Only part of the board was read (a Workday or Teamtailor board cut short by the run's time limit, a Workday board where some jobs can't be reached through its public search, or a SmartRecruiters board that stops paging early): new jobs seen in the part that was read are returned as usual, but no jobs are reported as removed, and saved jobs that weren't seen are kept. The company row has status
partialand a note; if there are no new jobs, that row is free. On boards that are always read only in part, closed jobs are therefore not reported as removed. - A board suddenly lists no jobs after the last run saw some: this is treated as unconfirmed. The company gets a free
empty_unconfirmedrow, nothing is reported as removed and the saved list is kept. If the next run also reads 0 jobs, the saved jobs are then returned asremoved.
Job rows are only charged when they are delivered, so none of these cases charges for rows that weren't returned.
The job lists are kept in a named key-value store in your account (stateStoreName). Use a different store name for each separate watch list. If a run stops early because it reached your maximum charge, the changes it didn't deliver are reported on the next run, not lost.
Pricing
This Actor uses pay-per-event pricing. You pay for results, not for compute:
| Event | When it is charged | Price |
|---|---|---|
| Actor start | Once per run (per GB of memory; the default 256 MB run counts as one start) | $0.00005 |
| Job | Each job row returned (in monitor mode, each new or removed job). Jobs removed by your filters are not charged | $0.002 |
| Company resolved | Each company whose board is found and read (normal mode, and the first monitor run), including when no jobs match your filters | $0.002 |
| Monitor check, no change | Monitor mode: a company with no new or removed jobs | $0.0005 |
Companies that can't be found are never charged. Higher Apify plans get tier discounts (Silver −10%, Gold −20%). Prices on the Actor's Pricing tab are authoritative.
Examples at the base price:
- One run over 20 companies with 100 open jobs each: $0.00005 + 20 × $0.002 + 2,000 × $0.002 = about $4.04.
- A daily monitor run over the same 20 companies, where 3 companies changed by 2 jobs each: $0.00005 + 17 × $0.0005 + 6 × $0.002 = about $0.021.
- The first example with filters that keep 10 jobs per company: $0.00005 + 20 × $0.002 + 200 × $0.002 = about $0.44.
The Actor respects the maximum cost per run you set: it stops adding rows when the limit is reached and says so in the run's status message.
Use it from code, spreadsheets or an AI agent
-
Schedule it: Console > Schedules, daily, with
monitorModeon, to get a new-jobs feed. -
Google Sheets, Make, Zapier, n8n, Slack: use the Actor's Integrations tab to send each run's dataset where you need it.
-
API (Python):
from apify_client import ApifyClientclient = ApifyClient("<YOUR_APIFY_TOKEN>")run = client.actor("yourevenings/careers-jobs-api").call(run_input={"companies": ["stripe.com", "ashby:ramp"]})for item in client.dataset(run["defaultDatasetId"]).iterate_items():print(item["company"], item.get("title"), item.get("location"), item.get("salaryMin")) -
AI agents: the Actor can be run through the Apify MCP server, so Claude, ChatGPT or Cursor agents can call it with their own input.
AI agents can pay for runs themselves
AI agents can run this Actor and pay with stablecoins such as USDC through the x402 or MPP protocols, with no Apify account needed. The agent buys a prepaid, spend-capped Apify API token from Apify's Agent General Interface (AGI) and then runs the Actor with it as normal. Prepaid tokens only run Actors that use limited permissions, and this Actor does. Agentic payments are an experimental Apify feature, and the terms (minimum amount, expiry, usage limits) are set by Apify. See Apify's docs: Let your AI agent pay for Actor runs, x402 and MPP.
Tips
- Run once with domains, then switch to the
ats:tokenvalues from theboardTokencolumn. Lookups are then exact and faster. - Large boards can have 500–1,000+ jobs. Use the job filters to get (and pay for) only the jobs you need, and
maxJobsPerCompanywhile you test. - Turn on
includeDescriptiononly if you need the full text. It makes the dataset much larger.
FAQ
Is this an official Greenhouse, Lever, Ashby or Workday product? No. It's an independent tool. It isn't affiliated with or endorsed by Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee or Workday. The names are used only to describe which public job boards it reads.
Where does the data come from? From the public job-board endpoints the ATS vendors publish so employers' openings can be shown on careers sites and job boards, and for Workday from the public job search each career site uses. No login, no browser automation and no proxies are used. Requests are rate-limited to be polite.
Why was my company not found?
It may use an ATS that isn't supported yet (for example SuccessFactors, iCIMS or an in-house careers site), its Workday career site may use a different tenant name from its domain, or its board token may not match its domain. If you know the board URL, pass it directly (for example https://jobs.ashbyhq.com/yourcompany or https://yourcompany.wd5.myworkdayjobs.com/External).
Could a guessed board belong to a different company with the same name?
It can happen with very generic names. The Actor checks company names and job-link domains to reduce this, and every row shows detectionMethod and boardToken so you can verify. Explicit tokens and board URLs avoid the issue entirely.
How do I know I got every job?
Each job row has companyTotalJobs, the board's open-job count before your filters and limits, and COMPANY-STATUS shows per company how many jobs the board had, how many were returned and how many your filters removed. In normal mode, if returned plus filteredOut is lower than totalJobs, the note says why: maxJobsPerCompany, your maximum cost per run, or (on Workday) jobs its public search couldn't reach in time. (In monitor mode returned counts new and removed jobs, so it isn't compared with the board total.)
How fresh is the data? Every run reads the boards live, so jobs are current as of the run.
Is it legal to use this data? The Actor reads only job postings that employers publish on public job boards, and it drops personal contact details. You're responsible for using the data in line with the laws that apply to you (for example GDPR) and the terms of the job boards and sites you use it with.
Is there a free Greenhouse jobs API? Greenhouse, Lever and Ashby publish public job-board endpoints, but each has its own format and you have to know every company's board token. This Actor tries to find the token from the domain (or takes the token or board URL if you know it) and returns one schema for all nine systems. You pay per job returned and per company resolved; companies that can't be found are free.
Am I charged for jobs my filters remove? No. Filters run before any job row is pushed, so filtered-out jobs are never returned or charged. Each company whose board is found is still charged the company-resolved event once (also when no jobs match), plus the per-run start fee. Companies that can't be found are free.
Which ATSs are supported? Exactly nine: Greenhouse, Lever (including its EU instance), Ashby, Workable, SmartRecruiters, Recruitee, Workday, Personio (only for employers whose public Personio job feed is switched on) and Teamtailor (from the career site's public RSS feed, which has no salary or employment type). BambooHR, iCIMS, SuccessFactors and other systems are not covered yet. They are being considered for future versions, but there is no date. Open an issue on the Actor's Issues tab to request others.
Feedback
Found a wrong match, a missing field or a company that should work? Open an issue on the Issues tab with the input line and run ID, and it'll be looked at quickly.