# ATS Jobs API: Greenhouse, Lever & Ashby (`atarivo/ats-jobs-api-greenhouse-lever-ashby`) Actor

Every open job on the Greenhouse, Lever and Ashby boards you list, one row per job: title, company, location, remote flag, department, posted date, apply URL, ATS and a dedup key, description on request. Board slugs or careers URLs in. Public job-board APIs only: no login, no personal data.

- **URL**: https://apify.com/atarivo/ats-jobs-api-greenhouse-lever-ashby.md
- **Developed by:** [Atarivo Enterprises Inc.](https://apify.com/atarivo) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $2.00 / 1,000 job scrapeds

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 API: Greenhouse, Lever & Ashby returns every open job on the company job boards you
list, as clean rows with the same fields whichever applicant tracking system (ATS) the company
uses: title, company, location, remote flag, department, posted date, apply URL, ATS and a
dedup key. It is built for job aggregators, recruiters, labour-market researchers and AI agents
that need fresh postings straight from the source. To try it, keep the sample input and press
**Start**. The sample reads three public boards and finishes in a few seconds.

### What does ATS Jobs API: Greenhouse, Lever & Ashby do?

- Returns **one dataset row per open job** in one normalised schema, so Greenhouse jobs, Lever
  jobs and Ashby jobs can go into the same table without any mapping.
- Accepts **board slugs or careers URLs**: `job-boards.greenhouse.io/<board>`,
  `jobs.lever.co/<site>`, `jobs.ashbyhq.com/<name>`, the matching API URLs, `ats:slug`
  (e.g. `lever:acme`), or a bare slug that it tries on Greenhouse, then Lever, then Ashby.
- Optionally adds the **job description as plain text** (`includeDescription`).
- **Removes duplicates** within a run by `dedup_key` (`ats:job_id`), so the same board listed
  twice is charged once per job.
- Calls **only three hosts**, the public job-board APIs: `boards-api.greenhouse.io`,
  `api.lever.co` and `api.ashbyhq.com`. It sends an honest User-Agent that names this Actor,
  reads and obeys each host's robots.txt (including `Crawl-delay`), sends at most 2 requests
  per second per host, and retries a failed request once.
- **No login, no cookies, no proxies, no personal data.** It reads job postings that the
  employers publish for anyone to see. It does not look for or extract recruiter or
  candidate contact details; a description is returned as the employer published it.
- Does **not** read Workday, Indeed, LinkedIn or any other aggregator. Those inputs are refused
  with a clear message before anything is fetched or charged.

### How to use the Greenhouse, Lever and Ashby jobs API

1. Put one board per line in **Job boards**. Copy the board URL from the company's careers
   page, or type the slug. Up to 200 boards per run.
2. Optionally tick **Include the job description text**, and set **Max jobs per board**
   (default 1,000).
3. Press **Start**. Open the **Output** tab for the jobs table, or read the dataset through the
   API in JSON, CSV or Excel. The `RUN_SUMMARY` record in the key-value store says, per board,
   which ATS answered and how many jobs were found.

Calling it from an AI agent: `{"boards": ["lever:acme", "https://jobs.ashbyhq.com/acme"]}`. The
description above is also the Actor's tool description in the Apify MCP server.

Run it on a schedule and compare `dedup_key` values between runs to see which jobs are new and
which were closed.

### Pricing

| Event | What you pay for | Price |
|---|---|---|
| `job-scraped` | One job returned as a row | $0.0020 |

Each run also has a start fee of $0.001. A board that does not exist (HTTP 404 on every ATS
tried) or that did not answer after a retry costs one `job-scraped` event for its error row.
A board skipped because of robots.txt, or a response this Actor could not read, is never
charged. Duplicates are never charged. Set **Max cost per run** to cap a run; the Actor stops
cleanly at the cap and says so in its status message. Platform usage is included (no "+usage"
charges).

### Input

| Field | Type | Required | Notes |
|---|---|---|---|
| `boards` | array of strings | yes | 1 to 200 entries: board URLs, `ats:slug`, or bare slugs. Aggregator, Workday and other ATS URLs are refused, and so are EU-hosted Greenhouse and Lever boards. |
| `includeDescription` | boolean | no | Default `false`. Adds `description_text`. Same price. |
| `maxJobsPerBoard` | integer | no | 1 to 10,000; default 1,000. Caps the jobs (and the cost) per board. |

```json
{
  "boards": ["greenhouse", "https://jobs.lever.co/palantir", "https://jobs.ashbyhq.com/ashby"],
  "includeDescription": false,
  "maxJobsPerBoard": 10
}
```

### Output

One row per job:

```json
{
  "title": "Senior Data Engineer",
  "company": "acme",
  "location": "Remote - United States",
  "remote": true,
  "department": "Engineering",
  "posted_at": "2026-10-01T14:30:00Z",
  "apply_url": "https://jobs.lever.co/acme/00000000-0000-4000-8000-000000000000/apply",
  "ats": "lever",
  "board": "acme",
  "job_id": "00000000-0000-4000-8000-000000000000",
  "dedup_key": "lever:00000000-0000-4000-8000-000000000000"
}
```

`remote` is `true` or `false` when the ATS says so and `null` when it does not. `posted_at` is
ISO 8601 in UTC. `company` is the company name from Greenhouse; Lever and Ashby do not return
one, so it is the board slug. A board that failed gives one row with `error`, `message`,
`tried` and `charged` instead. Run storage is kept for your plan's data-retention period, then
deleted by Apify.

### Other Actors by Atarivo

Every Atarivo Actor follows the same rules: limited permissions, no "+usage" pricing, charges
only after results are saved, and at least one result row per run.

- **[PDF, Image & Word to Text and Markdown (OCR)](https://apify.com/atarivo/pdf-image-text-markdown-extractor)**: returns the text, Markdown, tables and page facts of a PDF, PNG, JPEG, TIFF or Word .docx file, one dataset row per page, plus RAG chunks with page spans. OCR runs only on scanned or unreadable pages. First page free.
- **[Printable Puzzle PDF Generator: word search, sudoku, maze](https://apify.com/atarivo/printable-puzzle-pdf-generator)**: returns one printable PDF of word search, sudoku, maze or nonogram puzzles with an answer key. Every puzzle is solver-verified to have exactly one solution. Letter or A4. First 3 puzzles per run free.

### FAQ, disclaimers and support

**Is it legal?** It reads only the public, unauthenticated job-board endpoints that each ATS
documents for building job sites: Greenhouse's Job Board API ("Job Board data is publicly
available, so authentication is not required for any GET endpoints"), Lever's Postings API and
Ashby's public Job Posting API. It honours robots.txt and rate limits. You are responsible for
how you use the data, including any terms of the employers whose postings you republish.

**Why is my board "not found"?** Check the slug in the board's URL. Greenhouse and Lever boards
hosted in the EU are not supported yet.

**Why are some fields null?** The ATS did not publish them for that job.

**Is it affiliated with Greenhouse, Lever or Ashby?** No. The names describe the data source
only.

**Something is wrong.** Open an issue on the **Issues** tab with the run ID. Issues are
answered within 14 days.

This Actor is provided as is, under Apify's Standard Actor Contract. It is not affiliated with
or endorsed by Greenhouse, Lever or Ashby.

# Actor input Schema

## `boards` (type: `array`):

One board per line, up to 200 per run. Accepted: a board URL (job-boards.greenhouse.io/acme, jobs.lever.co/acme, jobs.ashbyhq.com/acme), a slug with its ATS (greenhouse:acme, lever:acme, ashby:acme), or a bare slug (acme), which is tried on Greenhouse, then Lever, then Ashby. Aggregators (Indeed, LinkedIn, ...), Workday and other ATSs are refused.

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

Add description_text (the posting as plain text) to every row. Off by default: rows stay small. The price per job is the same either way.

## `maxJobsPerBoard` (type: `integer`):

Stop reading a board after this many jobs. From 1 to 10000; default 1000. Each job is one charged event, so this also caps the cost per board.

## Actor input object example

```json
{
  "boards": [
    "greenhouse",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ashby"
  ],
  "includeDescription": false,
  "maxJobsPerBoard": 10
}
```

# Actor output Schema

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

One row per open job (title, company, location, remote, department, posted_at, apply_url, ats, board, job_id, dedup_key; description_text when includeDescription is on), plus one row with error, message, tried and charged per board that could not be read.

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

Per board: the ATS that answered, the outcome and the number of jobs found and delivered.

# 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 = {
    "boards": [
        "greenhouse",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ashby"
    ],
    "maxJobsPerBoard": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("atarivo/ats-jobs-api-greenhouse-lever-ashby").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 = {
    "boards": [
        "greenhouse",
        "https://jobs.lever.co/palantir",
        "https://jobs.ashbyhq.com/ashby",
    ],
    "maxJobsPerBoard": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("atarivo/ats-jobs-api-greenhouse-lever-ashby").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 '{
  "boards": [
    "greenhouse",
    "https://jobs.lever.co/palantir",
    "https://jobs.ashbyhq.com/ashby"
  ],
  "maxJobsPerBoard": 10
}' |
apify call atarivo/ats-jobs-api-greenhouse-lever-ashby --silent --output-dataset

```

## MCP server setup

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

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/j5W7FbbabzmafTLux/builds/rREVB5ZlvBSLcTp09/openapi.json
