# Multi-ATS Jobs API – Greenhouse, Lever, Ashby & More (`chris_elder/multi-ats-jobs-api`) Actor

Fetch live open jobs from Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable public board APIs. Normalised title, location, department, salary, remote flag and apply URL. No API key. $1 per 1,000 jobs; failed boards free.

- **URL**: https://apify.com/chris_elder/multi-ats-jobs-api.md
- **Developed by:** [Chris Elder](https://apify.com/chris_elder) (community)
- **Categories:** Jobs, Developer tools, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.60 / 1,000 job listeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

## Multi-ATS Jobs API – Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee, Workable

**Multi-ATS Jobs API** pulls **live open roles** from the public job-board JSON endpoints that employers already publish on Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee and Workable. Give it company board slugs; get normalised rows (title, location, department, remote flag, salary when present, apply URL) ready for Clay, Sheets, agents and hiring-signal monitors.

✅ Pay per result: **$1 per 1,000 jobs** · 🆓 Failed boards are never charged · 🔑 No API key

[▶ Try it with one click](#how-to-use-it) · [📄 Real example output](#output-example-from-a-real-public-run) · [💲 Pricing](#how-much-does-it-cost-to-pull-jobs) · [🔌 API & integrations](#integrations-api-ai-agents-make-zapier) · [❓ FAQ](#faq) · [🛟 Support](#support-reliability-and-feature-requests)

### What does Multi-ATS Jobs API do?

- 🧩 **Six ATS in one Actor** – Greenhouse, Lever, Ashby, SmartRecruiters, Recruitee, Workable public boards
- 📦 **Normalised rows** – same fields across providers (title, department, location(s), remote, employment type, salary, posted date, apply URL)
- 🔎 **Filters** – keyword list and remote-only without post-processing
- 📄 **Optional descriptions** – pull HTML/text where the board API supports it
- 🛡️ **No personal data** – recruiter names and emails are not collected; job ads only
- 🆓 **Failed boards free** – 404 / empty / HTTP errors are listed for free and not charged
- 🤖 **Agent-ready** – PPE pricing, MCP-friendly, works from Clay / Make / n8n

### Use cases

- **Recruiters & talent teams** – monitor competitor or customer career pages without six scrapers
- **Hiring-signal products** – seed a company list and track new roles over time
- **RevOps / Clay users** – enrich accounts with “is hiring for X” from live boards
- **Researchers** – build lawful job datasets from official syndication endpoints

### How to use it

1. Click **Try for free** – the prefill queries Airbnb (Greenhouse), Notion (Ashby) and Spotify (Lever), capped at 5 jobs each (a few cents).
2. Replace `companies` with your board slugs (`ats` + `board`).
3. Optionally set `keywordFilter`, `remoteOnly`, or `includeDescription`.
4. Download the dataset (JSON/CSV) or pipe it to Sheets / your CRM.

#### Input example

```json
{
  "companies": [
    { "ats": "greenhouse", "board": "airbnb" },
    { "ats": "ashby", "board": "notion" },
    "lever:spotify"
  ],
  "maxJobsPerCompany": 50,
  "remoteOnly": false
}
```

Other options: `atsFilter`, `includeDescription`, `keywordFilter`, `maxJobsTotal`, `requestDelayMs`, `timeoutSecs`.

#### Output example (from a real public run)

```json
{
  "ats": "greenhouse",
  "board": "airbnb",
  "company": "airbnb",
  "jobId": "8184174",
  "title": "Software Engineer",
  "department": "Engineering",
  "location": "United States",
  "locations": ["United States"],
  "isRemote": false,
  "employmentType": null,
  "salary": null,
  "postedAt": "2026-09-15T12:00:00.000Z",
  "applyUrl": "https://careers.airbnb.com/positions/8184174?gh_jid=8184174"
}
```

| Field | Meaning |
|---|---|
| `ats` / `board` | Provider and public board slug you passed in |
| `title` / `department` / `location` | Normalised job facts |
| `isRemote` | Heuristic from location / ATS remote flags |
| `applyUrl` | Public application link |
| `error` | Present only for failed boards (not charged) |

### How much does it cost to pull jobs?

| Event | Free / Bronze | Silver | Gold+ |
|---|---|---|---|
| Actor start (× memory GB) | $0.0005 | $0.0005 | $0.0005 |
| Job listed | $0.001 | $0.0008 | $0.0006 |

**Failed boards, filtered-out jobs and empty boards are free.**

| Job | Approx. cost |
|---|---|
| Prefill (≤15 jobs, 512 MB) | ≈ $0.015 + $0.0005 start |
| 1,000 jobs | $1.00 |
| 10,000 jobs (Gold) | $6.00 |

Use **Max cost per run** to hard-cap spend.

### Integrations (API, AI agents, Make, Zapier)

```bash
curl -X POST "https://api.apify.com/v2/acts/chris_elder~multi-ats-jobs-api/run-sync-get-dataset-items?token=YOUR_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies":[{"ats":"greenhouse","board":"airbnb"}],"maxJobsPerCompany":20}'
```

MCP: `https://mcp.apify.com/?tools=chris_elder/multi-ats-jobs-api`

Also works from Make, Zapier, n8n, Clay (Run Actor / enrichment).

### Limits and good to know

- Board slugs must be the **public careers token** (e.g. Greenhouse board token), not an internal ID.
- Some companies disable public boards → HTTP 404 (listed free).
- Workable’s widget API only returns what the employer exposes on the embed; some accounts return an empty list.
- Descriptions can be large; leave `includeDescription` off unless you need them.
- Respect each employer’s rate limits; default delay is 300 ms between boards.

### Is it legal?

This Actor calls **official, unauthenticated job-board APIs** that employers publish for syndication (Greenhouse Job Board API, Lever postings API, Ashby public posting API, SmartRecruiters postings API, Recruitee offers API, Workable widget API). It collects **job advertisements**, not personal profiles. You are responsible for how you use the data and for complying with applicable law. See [Apify’s legal overview](https://blog.apify.com/is-web-scraping-legal/).

### FAQ

**Do I need API keys?** No – these board endpoints are public.

**What is a board slug?** The public token in the careers URL, e.g. `airbnb` in Greenhouse, `notion` in Ashby, `spotify` in Lever.

**Can I track changes over time?** Yes – schedule the Actor on a company list and diff `jobId` sets (or pair with a hiring-signals workflow).

**Why did a board return an error row?** Usually a wrong slug or a disabled public board. Those rows are free.

### Support, reliability and feature requests

- Failed boards are free.
- Every release is tested on real public boards; the one-click example works.
- Issues answered within 2 business days via the Actor **Issues** tab.
- Breaking input or price changes are announced in this README first.

Built by Chris Elder with AI-assisted development; every release is reviewed and tested.

### Need the data done for you?

If you'd rather not set up runs yourself, the UK company behind these tools (GPT Shop Ltd) offers a fixed-price done-for-you scrape. Tell us the website and the fields you need, and you get a clean CSV or Google Sheet within 48 hours of the confirmed brief, up to 5,000 rows, for £149 or $179. If we can't get the data, you're refunded in full. [See the done-for-you scraper service](https://sme-free-tools.pages.dev/done-for-you-scraper/?utm_source=apify\&utm_medium=readme\&utm_campaign=multi-ats-jobs-api)

### More tools by Chris Elder

[Sitemap URL Extractor](https://apify.com/chris_elder/sitemap-url-extractor) · [PDF to Markdown](https://apify.com/chris_elder/pdf-to-markdown) · [Bulk Lighthouse Auditor](https://apify.com/chris_elder/lighthouse-batch-auditor) · [Bulk WHOIS Lookup](https://apify.com/chris_elder/bulk-whois-domain-lookup) · [Image to Text OCR](https://apify.com/chris_elder/image-to-text-ocr) · [HTTP Request Sender](https://apify.com/chris_elder/http-request-sender) · [all tools](https://apify.com/chris_elder)

# Actor input Schema

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

List of company boards to query. Each item is {"ats": "greenhouse|lever|ashby|smartrecruiters|recruitee|workable", "board": "slug"} or a string "ats:slug" (e.g. "greenhouse:airbnb"). The board slug is the public careers board token employers publish (not a secret).

## `atsFilter` (type: `array`):

Optional. If set, only companies whose ats is in this list are queried.

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

When true, fetch full description where the board API supports it (Greenhouse content=true, Lever already includes). Increases response size.

## `keywordFilter` (type: `array`):

Keep only jobs whose title, department or location contains any of these words (case-insensitive). Empty = keep all.

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

Keep only jobs flagged as remote / anywhere / hybrid-remote.

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

Cap jobs returned per board (after filtering).

## `maxJobsTotal` (type: `integer`):

Hard cap across the whole run.

## `requestDelayMs` (type: `integer`):

Politeness delay between companies.

## `timeoutSecs` (type: `integer`):

Timeout per board (seconds)

## Actor input object example

```json
{
  "companies": [
    {
      "ats": "greenhouse",
      "board": "airbnb"
    },
    {
      "ats": "ashby",
      "board": "notion"
    },
    {
      "ats": "lever",
      "board": "spotify"
    }
  ],
  "atsFilter": [],
  "includeDescription": false,
  "keywordFilter": [],
  "remoteOnly": false,
  "maxJobsPerCompany": 500,
  "maxJobsTotal": 5000,
  "requestDelayMs": 300,
  "timeoutSecs": 30
}
```

# Actor output Schema

## `overview` (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": [
        {
            "ats": "greenhouse",
            "board": "airbnb"
        },
        {
            "ats": "ashby",
            "board": "notion"
        },
        {
            "ats": "lever",
            "board": "spotify"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("chris_elder/multi-ats-jobs-api").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": [
        {
            "ats": "greenhouse",
            "board": "airbnb",
        },
        {
            "ats": "ashby",
            "board": "notion",
        },
        {
            "ats": "lever",
            "board": "spotify",
        },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("chris_elder/multi-ats-jobs-api").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": [
    {
      "ats": "greenhouse",
      "board": "airbnb"
    },
    {
      "ats": "ashby",
      "board": "notion"
    },
    {
      "ats": "lever",
      "board": "spotify"
    }
  ]
}' |
apify call chris_elder/multi-ats-jobs-api --silent --output-dataset

```

## MCP server setup

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

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/GkEUBVd3DodlyIPhD/builds/DnQpaeO3Z6081rwuY/openapi.json
