# ATS Jobs Feed: Greenhouse, Lever, Ashby & More (`avisommer/ats-jobs-feed`) Actor

Get every open job from any company's Greenhouse, Lever, Ashby, SmartRecruiters or Recruitee board in one clean format, with salary, remote, seniority and new-jobs-only mode.

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

## Pricing

from $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, SmartRecruiters & Recruitee

Get **every open job from any company's careers page** in one clean, consistent format: title, department, location, remote/hybrid, seniority, **salary range**, posting date, apply link and full description.

Just paste career page URLs (or company names) and go. No proxies or logins are needed. It reads each platform's official public job-board API, so it's fast and reliable, and it doesn't break when a website gets redesigned.

### Why use it

- **6 job platforms, 1 format.** Greenhouse, Lever (US and EU), Ashby, **Workday**, SmartRecruiters and Recruitee all come out in the same fields. Mix startups and Fortune 500 employers in one run.
- **Salary included.** Uses structured pay data where the platform has it (Ashby, Lever, Recruitee). Otherwise it pulls the pay range out of the description, e.g. "$160,000 - $210,000" or "184,000 USD – 287,500 USD" (common in US pay-transparency postings).
- **Only new jobs mode.** Schedule it daily or hourly and get just the jobs posted since the last run. You only pay for new jobs.
- **Auto-detect.** Don't know which system a company uses? Enter the company slug (e.g. `notion`) and every supported platform is checked.
- **Filters:** title keywords, excluded words, location, remote/hybrid/on-site, department, seniority, posted-within-N-days, salary-only.

### Use cases

- **Job alerts & job boards:** power a niche job board ("remote Rust jobs", "AI startup jobs") or a Slack/Discord alert.
- **Recruiting & sales intelligence:** see which companies are hiring for what. Hiring is a strong buying signal.
- **Market & salary research:** compare pay ranges by role, level and location across hundreds of companies.
- **Job seekers:** watch your dream companies and get new matching roles first.

### Input

| Field | What it does |
|---|---|
| `companies` | Career page URLs (`https://jobs.lever.co/palantir`, `https://jobs.ashbyhq.com/openai`, `https://boards.greenhouse.io/stripe`, `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`, `https://careers.smartrecruiters.com/ServiceNow`, `https://bunq.recruitee.com`), `ats:slug` pairs (`greenhouse:stripe`, `lever-eu:acme`), or a bare slug (auto-detect; Workday needs the full URL). |
| `keywords` / `excludeKeywords` | Keep or drop jobs by title words. Turn on `searchInDescription` to also match descriptions. |
| `locations` | e.g. `London`, `United States`, `Remote`. |
| `workplaceTypes` | `remote`, `hybrid`, `onsite`. |
| `departments`, `seniority`, `postedWithinDays`, `requireSalary` | More filters. |
| `onlyNew` + `stateKey` | Return only jobs not returned before (per monitor name). |
| `includeDescription` | Include description HTML and text (default on). |
| `maxJobsPerCompany` | Cap per company (0 = no limit). With `onlyNew`, each run moves on to the next unseen jobs. |

Example:

```json
{
  "companies": ["https://jobs.ashbyhq.com/openai", "greenhouse:stripe", "notion"],
  "keywords": ["engineer"],
  "workplaceTypes": ["remote", "hybrid"],
  "onlyNew": true,
  "stateKey": "eng-alerts"
}
```

### Output

Each job is one dataset item:

```json
{
  "id": "smartrecruiters:ServiceNow:744000159871179",
  "source": "smartrecruiters",
  "company": "ServiceNow",
  "companyName": "ServiceNow",
  "title": "Senior DevOps Engineer (Kubernetes) - Federal",
  "department": "Engineering, Infrastructure and Operations",
  "team": "Engineering",
  "location": "Santa Clara, CALIFORNIA, United States",
  "locations": ["Santa Clara, CALIFORNIA, United States"],
  "country": "US",
  "workplaceType": "onsite",
  "employmentType": "full-time",
  "seniority": "senior",
  "salaryMin": 161300,
  "salaryMax": 274200,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salarySource": "description",
  "postedAt": "2026-11-05T13:41:16.322Z",
  "url": "https://jobs.smartrecruiters.com/ServiceNow/744000159871179-senior-devops-engineer-kubernetes-federal",
  "applyUrl": "https://jobs.smartrecruiters.com/ServiceNow/744000159871179-senior-devops-engineer-kubernetes-federal?oga=true",
  "descriptionText": "…",
  "descriptionHtml": "…",
  "scrapedAt": "2026-11-05T13:44:56.215Z"
}
```

A per-company summary (found / not found / errors / counts) is saved to the run's key-value store as `OUTPUT`.

Export to JSON, CSV, Excel, or send results to Google Sheets, Slack, Zapier, Make or n8n through Apify integrations.

### Pricing

Pay per result: you pay only for jobs delivered to your dataset. Set a maximum cost per run in run options and the Actor stops cleanly when it's reached. With **Only new jobs** on, repeat runs charge only for jobs you haven't seen.

### FAQ

**Which companies are supported?** Any company whose public careers page runs on Greenhouse, Lever, Ashby, Workday, SmartRecruiters or Recruitee. That covers a large share of startups and tech companies. If a career URL is on a custom domain, use the company slug or the `ats:slug` form.

**Workday tips:** paste the careers URL (anything on `*.myworkdayjobs.com` or `myworkdaysite.com`). Title keywords are also sent to Workday's own search, so filtered runs on big employers are fast. Workday returns at most about 2,000 jobs per search, so use keywords for very large employers. Posting dates come from Workday and may be approximate ("Posted 3 days ago").

**How is seniority detected?** From the job title (intern, junior, senior, staff, principal, lead/manager, director, executive). Titles without a level are `null` (filter with `unspecified`).

**Is this legal?** It only reads public job-board APIs that these platforms provide for publishing job listings. It collects no personal data. Some company boards are intentionally excluded.

**Something's wrong?** Open an issue on the Actor's Issues tab with the company URL and it will be fixed quickly.

# Actor input Schema

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

Careers page URLs, e.g. https://jobs.lever.co/palantir, https://jobs.ashbyhq.com/openai, https://boards.greenhouse.io/stripe, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite; or "ats:slug" pairs (greenhouse:stripe, lever-eu:acme); or a bare company slug to auto-detect (Workday needs the full URL).

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

Keep jobs whose title contains any of these (case-insensitive). Leave empty for all jobs.

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

Drop jobs whose title contains any of these.

## `searchInDescription` (type: `boolean`):

Match keywords against the job description too, not just the title.

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

Keep jobs whose location contains any of these, e.g. "London", "United States", "Remote".

## `workplaceTypes` (type: `array`):

Keep only these workplace types.

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

Keep jobs whose department or team contains any of these.

## `seniority` (type: `array`):

Detected from the job title. "unspecified" keeps titles with no level.

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

Only jobs posted in the last N days. 0 = any time.

## `requireSalary` (type: `boolean`):

Keep only jobs where a salary range was found.

## `onlyNew` (type: `boolean`):

Remember jobs already returned and output only new ones. Ideal for scheduled runs and alerts. You are only charged for new jobs.

## `stateKey` (type: `string`):

Separate "only new" memory per monitor. Use a different name for each schedule.

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

Add description HTML and plain text. Turn off for faster, smaller output.

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

0 = no limit.

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

How many companies to fetch at the same time.

## Actor input object example

```json
{
  "companies": [
    "https://jobs.ashbyhq.com/openai",
    "https://jobs.lever.co/palantir",
    "smartrecruiters:ServiceNow",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "keywords": [
    "engineer"
  ],
  "searchInDescription": false,
  "postedWithinDays": 0,
  "requireSalary": false,
  "onlyNew": false,
  "stateKey": "default",
  "includeDescription": true,
  "maxJobsPerCompany": 100,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

One item per job posting (overview view).

## `jobsFull` (type: `string`):

Every field, including descriptions.

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

Per-company status (ok, not_found, error, excluded) and job counts.

# 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://jobs.ashbyhq.com/openai",
        "https://jobs.lever.co/palantir",
        "smartrecruiters:ServiceNow",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ],
    "keywords": [
        "engineer"
    ],
    "maxJobsPerCompany": 100
};

// Run the Actor and wait for it to finish
const run = await client.actor("avisommer/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://jobs.ashbyhq.com/openai",
        "https://jobs.lever.co/palantir",
        "smartrecruiters:ServiceNow",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ],
    "keywords": ["engineer"],
    "maxJobsPerCompany": 100,
}

# Run the Actor and wait for it to finish
run = client.actor("avisommer/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://jobs.ashbyhq.com/openai",
    "https://jobs.lever.co/palantir",
    "smartrecruiters:ServiceNow",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "keywords": [
    "engineer"
  ],
  "maxJobsPerCompany": 100
}' |
apify call avisommer/ats-jobs-feed --silent --output-dataset

```

## MCP server setup

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