# Greenhouse & Lever Jobs Scraper: Ashby, Workday (`mystique-lab/ats-jobs-feed`) Actor

Scrape every open job from Greenhouse, Lever, Ashby, Workable, SmartRecruiters and Workday career pages. Type a company name and get clean rows with title, location, department and job URL. No login, no API key. Flat $1 per 1,000 jobs; failed lookups free.

- **URL**: https://apify.com/mystique-lab/ats-jobs-feed.md
- **Developed by:** [Mystique Lab](https://apify.com/mystique-lab) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.00 / 1,000 results

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.

Learn more: https://docs.apify.com/actors/running/actors-in-store.md#pay-per-event

## What's an Apify Actor?

An Actor is a serverless cloud program that runs on the Apify platform. It has two run modes.
In Batch mode, an Actor accepts a well-defined JSON input, performs an action which can take anything from a few seconds to a few hours,
and optionally produces a well-defined JSON output, datasets with results, or files in key-value store.
In Standby mode, an Actor provides a web server which can be used as a website, API, or an MCP server.

Apify vocabulary and the platform model are defined once, in the agent quickstart at https://apify.com/agents.md.

## How to integrate an Actor?

If asked about integration, you help developers integrate Actors into their projects.
You adapt to their stack and deliver integrations that are safe, well-documented, and production-ready.

Do not guess an integration path. Every one of them is in the agent quickstart at https://apify.com/agents.md: the Apify MCP server, Agent Skills with the Apify CLI, the JavaScript and Python clients, the REST API, and the account-free path for an agent with no human to sign in. It also carries the rule on stating cost before the first paid run.

For examples already wired to this Actor's own input schema, see the [API](#api) section below.

Each client library has reference documentation the quickstart does not restate: [JavaScript/TypeScript](https://docs.apify.com/api/client/js/docs.md) (`npm install apify-client`) and [Python](https://docs.apify.com/api/client/python/docs.md) (`pip install apify-client`).

# README

## Greenhouse Jobs Scraper: Lever, Ashby, Workday & More

Get every open job from any company that hires through Greenhouse. Just type the company name, no board URL hunting. The same run also covers Lever, Ashby, Workable, SmartRecruiters and Workday, so one tool handles most company careers pages. You get clean job rows with title, location and job URL, ready for a spreadsheet or your own app. The price is a flat $1 per 1,000 jobs.

![ats-jobs-feed demo](https://api.apify.com/v2/key-value-stores/cRIPJiTuB8saU3ee6/records/ats-jobs-feed-demo.gif)

### What it does

- 6 ATS, 1 schema: the same fields for every company.
- Filters: keywords, exclude keywords, locations, remote only, posted within N days, caps.
- Monitor mode: set a Monitor name and a Schedule. Each run returns (and charges) only jobs
  it has not returned before under that name. The first run is the baseline.
- Salary range when the employer publishes it (Lever, Ashby).
- Workday boards over 2,000 jobs are split by job category automatically, so you still get all of them.
- Reads each ATS's public job-board feed. No login, no browser, no proxies.

### Who it's for

- Job boards and newsletters filling feeds from company career pages
- Recruiters and B2B sales teams watching who is hiring
- Job seekers tracking a shortlist of companies
- Analysts tracking hiring by team, location or remote share

### Input

| field | what it does |
|---|---|
| `companies` | Just a company name (`Stripe`, `Hugging Face`): we find its job board on Greenhouse, Lever, Ashby, Workable or SmartRecruiters. Or a careers-page URL (`https://www.notion.com/careers`), a job-board URL (`https://jobs.lever.co/spotify`), or `ats:slug` (`ashby:ramp`). **Workday: paste the careers URL**, e.g. `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`. |
| `companyPreset` | Ready-made company list: `ai-labs`, `fintech`, `dev-tools`, `big-tech-workday`. Added to your own list. |
| `preset` | Role filter: `software-engineering`, `ai-ml`, `data`, `sales-gtm`, `marketing`, `product-design`, `entry-level`, `leadership`, `remote-only`. Combines with your keywords. |
| `keywords` | Keep jobs whose title, department or description contains any of these. |
| `excludeKeywords` | Drop jobs whose title or department contains any of these. |
| `locations` | Keep jobs whose location contains any of these (`New York`, `Remote`, `Germany`). |
| `remoteOnly` | Only jobs marked remote or with "Remote" in the location. |
| `postedWithinDays` | Only jobs posted in the last N days (0 = off). |
| `includeDescription` | Full plain-text description (default on). Turn off for faster, smaller output. |
| `maxJobsPerCompany`, `maxJobs` | Caps (0 = no limit). |
| `monitorName` | Monitor mode. Same name on every scheduled run = new jobs only. The `SUMMARY` record also lists jobs removed since the last run (free). |
| `reportRemovedJobs` | List removed job IDs in `SUMMARY` (monitor mode). Default on. |

### Output (one row per job, real sample trimmed)

```json
{ "jobId": "ashby:ramp:34413f8d-…", "ats": "ashby", "companySlug": "ramp", "company": "ramp",
  "title": "Security Engineer, Cloud", "location": "New York, NY (HQ); Remote (US)",
  "isRemote": true, "department": "Engineering / Backend", "employmentType": "FullTime",
  "workplaceType": "Hybrid", "postedAt": "2026-04-07T17:12:35Z",
  "salary": { "min": 211400, "max": 290600, "currency": "USD", "interval": "1 YEAR" },
  "url": "https://jobs.ashbyhq.com/ramp/34413f8d-…", "description": "…",
  "isNewSinceLastRun": null, "scrapedAt": "…" }
```

Workday rows also have `postedOnText` (e.g. "Posted 3 Days Ago").
A `SUMMARY` record (key-value store) lists each company: ATS found, jobs on board, jobs returned, and any board not found.

### Pricing

**$1.00 per 1,000 jobs returned.** No start fee. Filtered-out jobs, boards not found, and
already-seen jobs in monitor mode are free. Set "Maximum cost per run" and the run stops cleanly there.

### FAQ

- **Which companies work?** Any public board on the 6 supported ATS. A company that isn't found is
  listed in SUMMARY; the run doesn't fail.
- **Bare slug not found?** Paste the careers-page URL instead. Workday always needs the URL.
- **Why is salary empty?** Only Lever and Ashby publish salary in their feeds, and only when the employer adds it.
- **iCIMS / Taleo?** Not supported yet. Tell us in Issues.
- **Is it legal?** It reads the same public job feeds the career pages use. No login, no personal data.

### Limits

- Only the 6 ATS above; custom career sites are not covered.
- Workday without `includeDescription`: `postedAt` is estimated from "Posted N Days Ago" ("30+ days" = 30),
  location may read "3 Locations", `company` is the Workday tenant name. With descriptions on you get exact
  values, but it's one extra request per job (slow on large boards).
- `keywords` can only match description text where a description is fetched (not Workable/SmartRecruiters).
- `postedAt` is whatever the ATS publishes (Greenhouse: first published; SmartRecruiters: release date).

### Terms & fair use

- Job posting text belongs to the employer. If you republish, link back to the job `url` and only reuse text you have the right to use.
- No personal data is collected.
- Not affiliated with Greenhouse, Lever, Ashby, Workable, SmartRecruiters or Workday.

### Which board did it find?

The `SUMMARY` record shows, per company, the board used (`ats`, `slug`), how it was found (`detectedVia`), and any other boards found under the same name (`otherBoardsFound`). If a name picks the wrong board, paste the job-board URL instead.

# Actor input Schema

## `companies` (type: `array`):

Company names (e.g. Stripe, Hugging Face), careers-page URLs (e.g. https://www.notion.com/careers), job-board URLs (https://jobs.lever.co/spotify), or 'ats:slug' (ashby:ramp). Names are auto-detected across Greenhouse, Lever, Ashby, Workable and SmartRecruiters, then the company's careers page. Workday: paste the careers URL, e.g. https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite.

## `companyPreset` (type: `string`):

Add a ready-made list of companies (added to any you type above).

## `preset` (type: `string`):

Adds keyword filters for a role family. Combines with your own keywords.

## `keywords` (type: `array`):

Keep jobs whose title, department or description contains any of these. Empty = all.

## `excludeKeywords` (type: `array`):

Drop jobs whose title or department contains any of these (e.g. intern, senior).

## `locations` (type: `array`):

Keep jobs whose location contains any of these, e.g. 'New York', 'Remote', 'Germany'.

## `remoteOnly` (type: `boolean`):

Keep only jobs marked remote, or with 'Remote' in the location.

## `postedWithinDays` (type: `integer`):

0 = no date filter.

## `includeDescription` (type: `boolean`):

Add the full job description text to each result. Turn off for smaller, faster output.

## `maxJobsPerCompany` (type: `integer`):

Stop after this many jobs from each company. 0 = no limit.

## `maxJobs` (type: `integer`):

Stop after this many jobs in total. 0 = no limit.

## `monitorName` (type: `string`):

Monitor mode: set a name and schedule the run. Each run returns (and charges) only jobs not seen in earlier runs with the same name. The run summary also lists jobs removed since the last run.

## `reportRemovedJobs` (type: `boolean`):

In monitor mode, list job IDs that disappeared since the last run in the SUMMARY record (free, not charged).

## Actor input object example

```json
{
  "companies": [
    "Stripe",
    "Hugging Face",
    "ashby:ramp"
  ],
  "companyPreset": "",
  "preset": "",
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": true,
  "maxJobsPerCompany": 0,
  "maxJobs": 100,
  "reportRemovedJobs": true
}
```

# Actor output Schema

## `jobs` (type: `string`):

No description

## `summary` (type: `string`):

No description

# API

You can run this Actor programmatically using our API. Below are code examples in JavaScript, Python, and CLI, as well as the OpenAPI specification and MCP server setup.

## JavaScript example

```javascript
import { ApifyClient } from 'apify-client';

// Initialize the ApifyClient with your Apify API token
// Replace the '<YOUR_API_TOKEN>' with your token
const client = new ApifyClient({
    token: '<YOUR_API_TOKEN>',
});

// Prepare Actor input
const input = {
    "companies": [
        "Stripe",
        "Hugging Face",
        "ashby:ramp"
    ],
    "maxJobs": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("mystique-lab/ats-jobs-feed").call(input);

// Fetch and print Actor results from the run's dataset (if any)
console.log('Results from dataset');
console.log(`💾 Check your data here: https://console.apify.com/storage/datasets/${run.defaultDatasetId}`);
const { items } = await client.dataset(run.defaultDatasetId).listItems();
items.forEach((item) => {
    console.dir(item);
});

// 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/js/docs

```

## Python example

```python
from apify_client import ApifyClient

# Initialize the ApifyClient with your Apify API token
# Replace '<YOUR_API_TOKEN>' with your token.
client = ApifyClient("<YOUR_API_TOKEN>")

# Prepare the Actor input
run_input = {
    "companies": [
        "Stripe",
        "Hugging Face",
        "ashby:ramp",
    ],
    "maxJobs": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("mystique-lab/ats-jobs-feed").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print(f"💾 Check your data here: https://console.apify.com/storage/datasets/{run.default_dataset_id}")
for item in client.dataset(run.default_dataset_id).iterate_items():
    print(item)

# 📚 Want to learn more 📖? Go to → https://docs.apify.com/api/client/python/docs/quick-start

```

## CLI example

```bash
echo '{
  "companies": [
    "Stripe",
    "Hugging Face",
    "ashby:ramp"
  ],
  "maxJobs": 100
}' |
apify call mystique-lab/ats-jobs-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,mystique-lab/ats-jobs-feed"
        }
    }
}
```

The hosted server signs you in with OAuth on first connect, so no API token belongs in this config. Clients without OAuth support can send an `Authorization: Bearer <APIFY_API_TOKEN>` header instead, using a token from API & Integrations in Apify Console (https://console.apify.com/settings/integrations).

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/uHXGyTSaQzH68Q4nk/builds/H5mdbYK9Gb5goj9RB/openapi.json
