# ATS Jobs Feed: Greenhouse, Lever, Ashby, Workday + 5 more (`angadseth/ats-jobs-feed`) Actor

Get every open job from a company's own careers board: Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, Recruitee, Personio and Breezy HR. One clean schema with salary, remote flag, location, department, dates and apply link. Auto-detects the ATS from a URL or company name.

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

## Pricing

$2.00 / 1,000 jobs

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

## ATS Jobs Feed: Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters jobs in one schema

Get **every open job from a company's own careers board** as clean JSON, CSV or Excel. Paste careers-page URLs or company names, and the Actor finds the applicant tracking system (ATS), reads its public job-board feed and returns all jobs in **one normalised schema**: title, department, team, locations, country, remote flag, workplace type, employment type, seniority, **salary range**, posting date, apply link and the full description.

Nine ATSs are supported: **Greenhouse, Lever, Ashby, Workday, Workable, SmartRecruiters, Recruitee, Personio and Breezy HR**. The data comes straight from the employer's own job board, so it is fresher and more complete than job aggregators, with no duplicates from reposts.

### Who uses it

- **Job boards and niche job sites** that list jobs from hundreds of companies and need one clean feed.
- **Recruiters and staffing agencies** watching target companies for new roles.
- **Sales and investment teams** that use hiring as a signal: a company hiring 10 data engineers or its first sales lead is a warm lead.
- **Analysts and HR teams** benchmarking salaries, remote policies and hiring by department.
- **AI agents** that need live job data. The Actor can be called as a tool through the Apify MCP server.

### Supported ATSs

| ATS | Careers URL looks like | Plain name works | Salary | Description |
|---|---|---|---|---|
| Greenhouse | `boards.greenhouse.io/discord`, `job-boards.greenhouse.io/discord` | yes | yes, when the company publishes pay ranges | yes |
| Lever (US and EU) | `jobs.lever.co/spotify`, `jobs.eu.lever.co/...` | yes | yes, when set | yes |
| Ashby | `jobs.ashbyhq.com/ramp` | yes | yes, when shown on the posting | yes |
| Workday | `nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite` | no, paste the URL | from the text, when written there | yes |
| Workable | `apply.workable.com/huggingface` | yes | from the text, when written there | yes |
| SmartRecruiters | `jobs.smartrecruiters.com/BoschGroup` | yes | from the text, when written there | yes |
| Recruitee | `bunq.recruitee.com` | yes | yes, when set | yes |
| Personio | `tado.jobs.personio.de` | yes | from the text, when written there | yes |
| Breezy HR | `company.breezy.hr` | yes | yes, when set | no |

When the ATS has no salary field, the Actor looks for a pay range written in the description (for example "$87,069 - $124,385" or "€60.000 - €75.000 per year") and fills `salaryMin`, `salaryMax`, `salaryCurrency` and `salaryPeriod` from it. The original wording is kept in `salaryText`.

### How to find a company's board name

1. Open the company's careers page and click any job.
2. Look at the address bar, or the address of the "Apply" button. It usually goes to one of the domains in the table above.
3. Paste that URL into **Companies**. The Actor reads the board name from it.

If you only know the name, type it (for example `ramp` or `discord`). The Actor tries every ATS except Workday and keeps the ones that answer. To skip the guessing, write `ashby:ramp`, or set **ATS for plain names**. Workday always needs the full careers URL, because its address contains a server number and a site name.

### Example inputs

Engineering jobs at three companies on three different ATSs:

```json
{
  "companies": ["https://boards.greenhouse.io/discord", "https://jobs.lever.co/spotify", "ramp"],
  "keywords": ["engineer"],
  "keywordsMatch": "title",
  "maxItems": 500
}
```

Remote roles posted in the last 7 days, without descriptions (small and fast):

```json
{
  "companies": ["https://jobs.ashbyhq.com/ramp", "https://apply.workable.com/huggingface", "https://boards.greenhouse.io/gitlab"],
  "remoteOnly": true,
  "postedWithinDays": 7,
  "includeDescription": false
}
```

Sales jobs in Germany at a large Workday and SmartRecruiters employer, at most 50 per company:

```json
{
  "companies": [
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "https://jobs.smartrecruiters.com/BoschGroup"
  ],
  "keywords": ["sales"],
  "locations": ["Germany"],
  "maxItemsPerCompany": 50
}
```

### Output

Each job is one record. Fields the ATS does not have are `null`, so every record has the same columns.

```json
{
  "jobId": "8910013002",
  "title": "Senior Machine Learning Engineer (Growth)",
  "company": "Discord",
  "companySlug": "discord",
  "ats": "greenhouse",
  "department": "Product Engineering",
  "team": null,
  "location": "San Francisco Bay Area",
  "locations": ["San Francisco Bay Area", "San Francisco, California, United States"],
  "country": "US",
  "isRemote": false,
  "workplaceType": null,
  "employmentType": null,
  "seniority": "senior",
  "salaryMin": 220000,
  "salaryMax": 275000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salaryText": "Base Salary: 220000-275000 USD",
  "postedAt": "2026-11-04T19:52:48.000Z",
  "updatedAt": "2026-11-04T20:10:36.000Z",
  "applyUrl": "https://job-boards.greenhouse.io/discord/jobs/8910013002",
  "jobUrl": "https://job-boards.greenhouse.io/discord/jobs/8910013002",
  "descriptionText": "Discord has a highly engaged community of millions of daily active users ...",
  "source": "https://boards-api.greenhouse.io/v1/boards/discord/jobs",
  "scrapedAt": "2026-11-05T14:55:58.783Z"
}
```

| Field | What it is |
|---|---|
| `jobId`, `title`, `company`, `companySlug`, `ats` | The job and where it came from |
| `department`, `team` | As the company files the job |
| `location`, `locations`, `country` | Main location, all locations, ISO country code (from the ATS, or worked out from the location) |
| `isRemote`, `workplaceType` | `isRemote` is `true` when the job can be done remotely in at least one of its locations; `workplaceType` is `remote`, `hybrid` or `onsite` as the ATS states it |
| `employmentType` | Full-time, Part-time, Contract, Internship or Temporary |
| `seniority` | intern, entry, mid, senior, lead, principal, manager, director or executive, from the ATS or the title |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod`, `salaryText` | Pay range and the period it is for (year, month, hour) |
| `postedAt`, `updatedAt` | ISO dates |
| `applyUrl`, `jobUrl` | Application form and job page |
| `descriptionText` | Full description as plain text (turn off with **Include description text**) |
| `descriptionHtml` | Original HTML, only when **Include description HTML** is on |

The run's **SUMMARY** record (key-value store) lists, for every company you entered, which ATS it was found on, how many jobs the board had, how many matched your filters and how many were saved, plus a clear message for any company that was not found.

### Filters

- **Keywords**: any of the words, in the title only or in the title, department and description.
- **Exclude words**: drop titles with any of these words (for example `intern`, `senior`).
- **Locations**: location contains any word; country names, codes and `Remote` work.
- **Departments**, **Remote jobs only**, **Posted within (days)**.
- **Max jobs** and **Max jobs per company** (newest jobs first).

### Pricing

You pay per job saved to the dataset. Jobs removed by your filters cost nothing. **Max jobs** is a hard cap, so you always know the most a run can cost.

### Schedules, webhooks and integrations

- **Daily new-job alerts**: save your input as a Task, add a Schedule (for example every morning), and set **Posted within (days)** to 1.
- **Google Sheets, Slack, email, Zapier, Make, n8n**: connect them in the Integrations tab to send each run's jobs where you need them.
- **Webhooks**: get a call when a run finishes and fetch the dataset from the API.
- **MCP / AI agents**: the Actor works as a tool in the Apify MCP server, so an agent can ask "what roles is Ramp hiring for in New York?" and get structured data back.

### FAQ

**Is this legal?** The Actor reads only the public job-board feeds that each ATS provides so companies can show their jobs on their own careers pages, and that anyone can open without logging in. It does not log in, solve captchas or get around any protection, and it reads at a polite pace. You are responsible for how you use the data.

**A company was "not found". Why?** Many companies host their careers page on their own domain, so the name you typed may not be their ATS board name. Open one of their jobs, copy the URL of the job or its Apply button, and paste that instead.

**Why do I get two boards for one name?** For a plain name the Actor tries every ATS, and sometimes two different companies use the same name on two ATSs. Each record has `ats` and `companySlug`, and you can set **ATS for plain names** or write `lever:name` to pick one.

**Does it work for very large employers?** Yes. Big SmartRecruiters and Workday boards are read page by page, and only the jobs that pass your filters and limits get the extra description call, so runs stay quick.

**How fresh is the data?** Live from the ATS at run time.

**Something broke or a field is missing?** Open an issue on the Actor's Issues tab and it will be fixed quickly.

### More Actors by angadseth

- [GeM Tenders Scraper (India Government e-Marketplace Bids)](https://apify.com/angadseth/gem-tenders-scraper): Get live GeM bids and reverse auctions from India's Government e-Marketplace
- [India eProcurement Tenders Scraper (CPPP + 30 State Portals)](https://apify.com/angadseth/india-eprocurement-tenders): Live government tenders from India's central eProcure (CPPP), central PSU, defence and 30+ state NIC eProcurement portals in one run.
- [Apple App Store Scraper: apps, ratings and reviews](https://apify.com/angadseth/app-store-scraper): Get Apple App Store apps, ratings and customer reviews from many countries in one run
- [Bluesky Scraper: Posts, Profiles, Followers and Feeds](https://apify.com/angadseth/bluesky-scraper): Scrape Bluesky without a login
- [Website Contact Enricher: Emails, Phones, Socials per Domain](https://apify.com/angadseth/website-contact-enricher): One clean lead row per company domain
- [Website Screenshot & PDF: full page, mobile, element, WebP](https://apify.com/angadseth/website-screenshot): Screenshots (PNG, JPEG, WebP) and PDFs of any list of URLs.
- [Remote Jobs Aggregator: RemoteOK, Jobicy, Arbeitnow + 2 more](https://apify.com/angadseth/remote-jobs-aggregator): Remote jobs from RemoteOK, Jobicy, Arbeitnow, Working Nomads and 4 Day Week in one clean feed.
- [PDF & Document Text Extractor: PDF, DOCX, PPTX, XLSX to Text](https://apify.com/angadseth/pdf-text-extractor): Turn public document URLs (PDF, DOCX, PPTX, XLSX, CSV, HTML, TXT) into clean text

# Actor input Schema

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

One company per line. Paste a careers-page URL (e.g. https://boards.greenhouse.io/discord, https://jobs.lever.co/spotify, https://jobs.ashbyhq.com/ramp, https://apply.workable.com/huggingface, https://jobs.smartrecruiters.com/BoschGroup, https://bunq.recruitee.com, https://tado.jobs.personio.de, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite) or just the company's board name (e.g. "ramp"). For a plain name the Actor tries every supported ATS and uses the ones that answer. You can also write "lever:spotify" to pick the ATS yourself. Workday always needs the full careers URL.

## `ats` (type: `string`):

Auto = detect the ATS from the URL, or try every ATS for a plain company name. Pick one ATS to look up plain names only there (faster, and avoids a different company with the same name on another ATS). URLs always use the ATS in the URL.

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

Keep jobs that contain any of these words, e.g. "engineer", "data", "sales". Case does not matter. Leave empty for all jobs.

## `keywordsMatch` (type: `string`):

Title only is stricter ("python" finds Python roles, not every job that mentions Python). Title or description finds more.

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

Drop jobs whose title contains any of these words, e.g. "intern", "senior", "manager".

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

Keep jobs whose location contains any of these words, e.g. "London", "Germany", "US", "Remote". Country names and two-letter codes both work.

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

Keep only jobs the ATS marks as remote, or whose location says remote.

## `departments` (type: `array`):

Keep jobs whose department or team contains any of these words, e.g. "Engineering", "Sales", "Marketing".

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

Keep only jobs first published in the last N days. 0 = any date.

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

Add the full job description as clean plain text (HTML removed). Turn off for smaller, faster results.

## `includeDescriptionHtml` (type: `boolean`):

Also add the original description HTML, e.g. to show it on your own job board.

## `maxItems` (type: `integer`):

Stop after this many jobs in total. You pay per job saved.

## `maxItemsPerCompany` (type: `integer`):

Newest jobs first. 0 = no limit per company (only Max jobs applies).

## `maxConcurrency` (type: `integer`):

How many companies to read in parallel. Each job board is still read at a polite pace.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/discord",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/ramp",
    "https://apply.workable.com/huggingface",
    "https://jobs.smartrecruiters.com/BoschGroup",
    "https://bunq.recruitee.com",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "ats": "auto",
  "keywordsMatch": "titleOrDescription",
  "remoteOnly": false,
  "postedWithinDays": 0,
  "includeDescription": true,
  "includeDescriptionHtml": false,
  "maxItems": 30,
  "maxItemsPerCompany": 5,
  "maxConcurrency": 5
}
```

# Actor output Schema

## `results` (type: `string`):

All jobs found in this run, as a dataset you can download in JSON, CSV or Excel.

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

Which ATS each company was found on, job counts per board and any warnings from this run.

# 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": [
        "https://boards.greenhouse.io/discord",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/ramp",
        "https://apply.workable.com/huggingface",
        "https://jobs.smartrecruiters.com/BoschGroup",
        "https://bunq.recruitee.com",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "maxItems": 30,
    "maxItemsPerCompany": 5
};

// Run the Actor and wait for it to finish
const run = await client.actor("angadseth/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": [
        "https://boards.greenhouse.io/discord",
        "https://jobs.lever.co/spotify",
        "https://jobs.ashbyhq.com/ramp",
        "https://apply.workable.com/huggingface",
        "https://jobs.smartrecruiters.com/BoschGroup",
        "https://bunq.recruitee.com",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ],
    "maxItems": 30,
    "maxItemsPerCompany": 5,
}

# Run the Actor and wait for it to finish
run = client.actor("angadseth/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": [
    "https://boards.greenhouse.io/discord",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/ramp",
    "https://apply.workable.com/huggingface",
    "https://jobs.smartrecruiters.com/BoschGroup",
    "https://bunq.recruitee.com",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "maxItems": 30,
  "maxItemsPerCompany": 5
}' |
apify call angadseth/ats-jobs-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,angadseth/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/Mcb2HgriyBhXyD99j/builds/FVu6N4za9o72p8oIB/openapi.json
