Greenhouse, Lever, Ashby & Workday Jobs: Careers Page Scraper avatar

Greenhouse, Lever, Ashby & Workday Jobs: Careers Page Scraper

Pricing

from $1.60 / 1,000 job returneds

Go to Apify Store
Greenhouse, Lever, Ashby & Workday Jobs: Careers Page Scraper

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

Your Evenings

Maintained by Community

Actor stats

0

Bookmarked

2

Total users

1

Monthly active users

23 minutes ago

Last modified

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.com link. 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-STATUS CSV 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 carries companyTotalJobs. If a board token you gave has moved to another supported job board, the jobs are read from the new board and the status says board_moved. Companies we can't find are free.
  • Your limits are honoured, with no hidden extra runs or double charges. maxJobsPerCompany caps 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 free duplicate row).
  • Alerts for new and removed jobs. Turn on monitorMode and schedule it daily: you get only jobs opened or closed since the last run, with firstSeenAt and lastSeenAt.
  • 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 Apify. Use it from Make, Zapier, n8n 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:

ATSTypical board URLNotes
Greenhouseboards.greenhouse.io/{token}, job-boards.greenhouse.io/{token}Posted pay ranges included
Leverjobs.lever.co/{token} (and the EU instance jobs.eu.lever.co)Posted salary range included
Ashbyjobs.ashbyhq.com/{token}Posted compensation included
Workableapply.workable.com/{token}
SmartRecruitersjobs.smartrecruiters.com/{token}
Recruitee{token}.recruitee.comPosted 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:

How it finds each company's jobs

For every line of input the Actor:

  1. 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).
  2. 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.
  3. If that fails, reads up to 4 pages of the company's website (your careers URL, /careers, /jobs and the homepage) and looks for links to a supported job board, including Workday career sites.
  4. If that fails too, checks whether Workday has a tenant with that name: each Workday host's public robots.txt says 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.
  5. 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 boardToken field in the output gives you the value to reuse.

Input

FieldWhat it doesDefault
companiesDomains, careers URLs, job-board URLs or ats:token values, one per line5 example companies
includeDescriptionAdds a plain-text descriptionText field (emails and phone numbers removed)off
maxJobsPerCompanyCaps rows per company (0 = all jobs), applied after the filters below0
titleKeywordsKeep jobs whose title contains any of these words or phrasesnone
excludeTitleKeywordsDrop jobs whose title contains any of these words or phrasesnone
locationsKeep jobs whose location contains any of these placesnone
remoteOnlyKeep only remote jobsoff
departmentsKeep jobs whose department or team contains any of these textsnone
postedWithinDaysKeep jobs posted within the last N days (0 = any date)0
keepJobsWithoutPostedDateWith postedWithinDays set, keep jobs whose board gives no posted dateon
monitorModeReturn only new and removed jobs since the previous runoff
emitBaselineOnFirstRunIn monitor mode, return all current jobs on the first runon
stateStoreNameNamed key-value store that remembers seen jobscareers-jobs-api-state
persistStateKeep firstSeenAt accurate across normal runson
scanCareersPageLook for job-board links on the company website if guessing failson
maxConcurrencyMax parallel HTTP requests5
requestTimeoutSecsPer-request timeout; failed requests are retried 3 times with backoff15

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 (developpeur matches "Développeur"). engineer matches "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: entwickler matches "Softwareentwickler (m/w/d)" and "Entwicklerin", and berater matches "Steuerberater". It doesn't match at the start of a word, so java doesn't match "JavaScript". There's no translation: developer doesn't match "Entwickler".
  • locations: whole words in the board's location text, ignoring case and accents (Zurich matches "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, so United Kingdom does not match a job listed only as "London". Remote also matches jobs the board flags as remote.
  • remoteOnly: keeps jobs with isRemote: true or workplaceType: "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 (eng matches "Engineering"). Department names are whatever each employer uses.
  • postedWithinDays: compares the board's postedAt with 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), salaryMin and salaryMax span them and salaryText lists each one.
  • isRemote is true when 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). workplaceType is remote, hybrid or onsite when the board says so.
  • Dates are ISO 8601 in UTC. Not every ATS publishes an update date, so updatedAt can be null.
  • postedAtUnknown is true when the board gives no posted date for the job.
  • postedAt is the board's own posting date (for Greenhouse first_published, never updated_at, which Greenhouse changes across whole boards at once). postedAtBasis says 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), or approximate-from-listing-text for Workday jobs whose listing only says "Posted 3 Days Ago" (converted to a UTC date, accurate to about a day; postedWithinDays allows one extra day for these). Workday jobs listed as "Posted 30+ Days Ago" have no postedAt unless their job page is read.
  • companyTotalJobs is the number of open jobs the company's board lists at run time, before your filters and maxJobsPerCompany. It is on every job row and on company rows for boards that were read (null for not_found, duplicate and error). Compare it with the rows you got to check nothing was left out. For SmartRecruiters it is the board's own totalFound count; 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 a status of not_found, no_open_jobs, no_matching_jobs (filters set, nothing matched), no_change, partial, empty_unconfirmed or fetch_failed (monitor mode, see Monitor mode), baseline_saved, duplicate, feed_disabled (Personio career page found but its public job feed is switched off) or error, plus a note explaining why. A board token you gave that was found on a different job board gets a board_moved row with fromAts, toAts and fromBoardToken (see Moved boards). When job filters are set, companies with matching jobs also get a company row (status ok, changes or partial_budget) with companyTotalJobs, filteredOut and jobsReturned. 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:

ColumnMeaning
inputThe line you entered
company, ats, boardTokenThe board it resolved to (empty if not found)
statusok, 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
totalJobsOpen jobs on the board before filters and limits (empty when the board wasn't read)
returnedJob rows returned for this input
filteredOutJobs (or monitor changes) your filters excluded
notePlain-English explanation
fromAts, toAtsFor 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_found row whose note mentions the Personio page with the feed switched off.
  • Unknown Personio names return a free not_found row.

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), fromBoardToken and a note. Job rows show the new board in ats and detectionMethod: "moved-board". Use the new ats and boardToken in future runs.
  • Not found anywhere: you get the same free not_found row 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_jobs as 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_change row, 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_failed row, 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 partial and 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_unconfirmed row, 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 as removed.

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:

EventWhen it is chargedPrice
Actor startOnce per run (per GB of memory; the default 256 MB run counts as one start)$0.00005
JobEach job row returned (in monitor mode, each new or removed job). Jobs removed by your filters are not charged$0.002
Company resolvedEach 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 changeMonitor 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 monitorMode on, 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 ApifyClient
    client = 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:token values from the boardToken column. 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 maxJobsPerCompany while you test.
  • Turn on includeDescription only 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.