# Company Jobs Scraper (Greenhouse, Lever, Ashby & more) (`roei-data/ats-jobs`) Actor

All open jobs from company career boards across six applicant-tracking systems in one normalized schema. Paste careers URLs or just company slugs; the Actor finds the board.

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

## Pricing

$1.50 / 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

## Company Jobs Scraper (Greenhouse, Lever, Ashby & more)

Type a company name and get all its open jobs. One run covers **Greenhouse, Lever (US and EU), Ashby, Workable, SmartRecruiters and Recruitee**, and every job comes back in one clean schema. You don't need to know which hiring system a company uses: a bare name such as `ramp` is detected automatically. It costs $1.50 per 1,000 jobs.

### What you can use it for

- **Hiring-signal lead lists.** Find companies hiring SDRs, data engineers or their first marketer, and pitch them while the budget is open.
- **Job boards and job alerts.** Feed a niche board (remote, AI, climate, your country) straight from company career pages, with no aggregator lag.
- **Competitor and market intel.** Track how many roles competitors open by department, location and seniority, week over week.
- **Job seekers and recruiters.** Monitor a target list of companies and get only new roles with **Posted within (days)**.
- **AI agents.** Call it as a tool through Apify MCP to answer questions like "Is Stripe hiring backend engineers in Dublin?".

### How it works

Paste careers-page URLs or just company slugs. The Actor reads each company's official public job board API, the same one their own careers site uses, and returns every open role: title, department, team, location, remote flag, employment type, salary (when published), posting date and links. You can filter by title keywords, location, remote and posting age. Turn on **Include description** for full plain-text job descriptions.

Because the data comes from official board APIs, runs are fast, cheap and stable. There's no browser, no login and no blocking.

### Input

| Field | Type | Description | Default |
|---|---|---|---|
| `companies` (required) | array | One per line: a careers board URL (boards.greenhouse.io/airbnb, jobs.lever.co/spotify, jobs.ashbyhq.com/ramp, apply.workable.com/huggingface, jobs.smartrecruiters.com/BoschGroup, bunq.recruitee.com), a pinned slug like lever:spotify, or a bare slug like ramp to auto-detect the system. |  |
| `keywords` | array | Keep jobs whose title contains any of these (case-insensitive). |  |
| `locations` | array | Keep jobs whose location or country contains any of these, e.g. London, Remote, US. |  |
| `remoteOnly` | boolean | Keep only jobs the board marks as remote. | false |
| `postedWithinDays` | integer | Keep jobs posted in the last N days. Empty means any time. |  |
| `includeDescription` | boolean | Add the full job description as plain text (makes items much larger). | false |
| `maxResults` | integer | Stop after this many jobs. 0 means no limit. You are charged per job. | 1000 |

### Output

Each result is one dataset item:

| Field | Type | Description |
|---|---|---|
| `id` | string | Stable id: ats:company:jobId |
| `title` | string | Job title |
| `company` | string | Board slug |
| `companyName` | string, null | Company display name when the board provides it |
| `ats` | string | greenhouse, lever, ashby, workable, smartrecruiters or recruitee |
| `department` | string, null | Department |
| `team` | string, null | Team |
| `location` | string, null | Location text (multiple joined by |) |
| `country` | string, null | Country or country code |
| `remote` | boolean, null | Remote flag from the board |
| `workplaceType` | string, null | remote, hybrid or on-site when provided |
| `employmentType` | string, null | Full-time, contract, etc. |
| `salary` | string, null | Salary range when published |
| `url` | string | Job page |
| `applyUrl` | string, null | Application page |
| `postedAt` | string, null | Published (ISO 8601) |
| `updatedAt` | string, null | Last updated (ISO 8601) |
| `description` | string, null | Plain-text description (when enabled) |

#### Example item

```json
{
  "id": "greenhouse:airbnb:8184174",
  "title": "Account Manager",
  "company": "airbnb",
  "companyName": "Airbnb",
  "ats": "greenhouse",
  "department": "Business Development",
  "team": null,
  "location": "London, United Kingdom",
  "country": null,
  "remote": false,
  "workplaceType": null,
  "employmentType": null,
  "salary": null,
  "url": "https://careers.airbnb.com/positions/8184174?gh_jid=8184174",
  "applyUrl": "https://careers.airbnb.com/positions/8184174?gh_jid=8184174",
  "postedAt": "2026-09-09T08:35:19.000Z",
  "updatedAt": "2026-09-30T00:00:54.000Z"
}
```

#### Example input

```json
{
  "companies": [
    "https://boards.greenhouse.io/airbnb",
    "https://jobs.lever.co/spotify",
    "https://jobs.ashbyhq.com/ramp",
    "https://apply.workable.com/huggingface",
    "https://bunq.recruitee.com",
    "https://jobs.smartrecruiters.com/BoschGroup"
  ],
  "maxResults": 600
}
```

### Pricing

Pay per result: **$1.50 per 1,000 results**. You are charged once per item in the dataset (event `result`), plus Apify's small per-run start fee. Platform compute is included.
Set **Max results** or a maximum run cost to cap spend; the Actor stops cleanly when either is reached.

### FAQ

#### Which companies are supported?

Any company whose career site runs on Greenhouse, Lever (US or EU), Ashby, Workable, SmartRecruiters or Recruitee. That covers a large share of tech and startup hiring. If you only know the company name, enter its slug (e.g. `ramp`) and the Actor checks all six systems.

#### How do I find a company's slug?

Open its careers page and look at the job links: `boards.greenhouse.io/airbnb` → `airbnb`, `jobs.lever.co/spotify` → `spotify`. You can paste the full URL instead.

#### How fresh is the data?

Live: every run reads the company's job board at that moment. Schedule it daily and filter by **Posted within (days)** to get only new roles.

#### Why did a company return nothing?

Either it uses a different hiring system, or the slug is wrong. The run log lists inputs with no job board found; if no input matches at all, the run fails with a clear message so you are not charged for an empty result.

### Reliability

Runs that return no data, mostly incomplete items, or mostly failed requests are marked **FAILED** with a reason instead of succeeding with an empty dataset. Each run stores a `RUN_SUMMARY` record in its key-value store.

# Actor input Schema

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

One per line: a careers board URL (boards.greenhouse.io/airbnb, jobs.lever.co/spotify, jobs.ashbyhq.com/ramp, apply.workable.com/huggingface, jobs.smartrecruiters.com/BoschGroup, bunq.recruitee.com), a pinned slug like lever:spotify, or a bare slug like ramp to auto-detect the system.

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

Keep jobs whose title contains any of these (case-insensitive).

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

Keep jobs whose location or country contains any of these, e.g. London, Remote, US.

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

Keep only jobs the board marks as remote.

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

Keep jobs posted in the last N days. Empty means any time.

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

Add the full job description as plain text (makes items much larger).

## `maxResults` (type: `integer`):

Stop after this many jobs. 0 means no limit. You are charged per job.

## Actor input object example

```json
{
  "companies": [
    "https://boards.greenhouse.io/airbnb",
    "https://jobs.lever.co/spotify",
    "ramp"
  ],
  "remoteOnly": false,
  "includeDescription": false,
  "maxResults": 1000
}
```

# Actor output Schema

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

All results in the default dataset.

## `runSummary` (type: `string`):

Counts, retries and any problems detected in 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/airbnb",
        "https://jobs.lever.co/spotify",
        "ramp"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("roei-data/ats-jobs").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/airbnb",
        "https://jobs.lever.co/spotify",
        "ramp",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("roei-data/ats-jobs").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/airbnb",
    "https://jobs.lever.co/spotify",
    "ramp"
  ]
}' |
apify call roei-data/ats-jobs --silent --output-dataset

```

## MCP server setup

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

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/40GjNEtEW9wFBbi8p/builds/x0u5xAtUmHKeV8M1a/openapi.json
