# ATS Jobs Aggregator - Greenhouse, Lever, Ashby (`apex_capricorn/ats-jobs-aggregator`) Actor

Pull every open job from company career boards hosted on Greenhouse, Lever and Ashby into one clean schema, via their official public posting APIs. Pay per job.

- **URL**: https://apify.com/apex_capricorn/ats-jobs-aggregator.md
- **Developed by:** [Joe Bashe](https://apify.com/apex_capricorn) (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

$1.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 Aggregator – Greenhouse, Lever & Ashby

> Built and maintained by an AI agent on behalf of the owner.

Collect every open job from company career boards hosted on **Greenhouse, Lever and Ashby** and get them in one clean, comparable schema. The Actor reads each ATS's **official public job-posting API** (the same endpoints companies use to embed their careers page) – no scraping of HTML pages, no login, no proxies.

### What you get

- Three ATS providers, one output schema (title, department, location, remote flag, employment type, salary range when published, posted/updated dates, apply URL, full description)
- **Attribution on every job**: `sourceUrl` (the public posting page) and `sourceBoardUrl` (the employer's public careers board) link back to the original
- Pass `ats:slug` (`greenhouse:stripe`), a careers-page URL, or just a slug to auto-detect
- Filters: keywords, excluded keywords, locations, departments, remote-only, posted within N days
- `maxItems` hard cap for cost control; the run stops cleanly when your spending limit is reached
- A run that produces **0 jobs is marked FAILED** (with the reason in the status message and the `RUN_SUMMARY` record) – you never pay for or silently receive an empty "success"

### Pricing (pay per result – no start fee)

You pay **only for results delivered**: $0.0010 per job (**$1.00 per 1,000**). There is **no charge per run start**. Set *Maximum cost per run* in Apify and the Actor stops when it is reached. Failed runs that produce nothing produce no result charges.

| Example | Cost |
|---|---|
| 100 jobs | $0.10 |
| 1,000 jobs | $1.00 |
| 25,000 jobs | $25.00 |

(Platform usage costs are minimal: the Actor uses plain HTTP requests, no browsers or proxies.)

### Example input

```json
{"companies":["greenhouse:stripe","greenhouse:airbnb","lever:spotify","ashby:ashby","notion"],"atsProviders":["ashby","lever","greenhouse"],"maxJobsPerCompany":40,"includeDescription":true,"maxItems":1000}
```

### Example output

```json
[
  {
    "id": "8172487",
    "ats": "greenhouse",
    "companySlug": "stripe",
    "company": "Stripe",
    "title": "Abuse Investigator",
    "department": "8611 Security Analytics",
    "team": null,
    "location": "Dublin",
    "locations": [
      "Dublin"
    ],
    "isRemote": false,
    "workplaceType": null,
    "employmentType": null,
    "salary": null,
    "postedAt": "2026-09-03T17:30:34.000Z",
    "updatedAt": "2026-10-22T13:16:14.000Z",
    "url": "https://stripe.com/jobs/search?gh_jid=8172487",
    "applyUrl": "https://stripe.com/jobs/search?gh_jid=8172487",
    "sourceUrl": "https://stripe.com/jobs/search?gh_jid=8172487",
    "sourceBoardUrl": "https://boards.greenhouse.io/stripe",
    "descriptionText": "Who we are\n\nAbout Stripe\n\nStripe is a financial infrastructure platform for businesses. Millions of companies - from the world’s largest enterprises to the most ambitious startups - use Stripe to accept payments, grow their revenue, and accelerate new business opportunities. Our mission is to increase the GDP of the internet, and we have a staggering amount of work ahead. That means you have an unprecedented opportunity to put the global economy within everyone's reach while doing the most important work of your career.\n\nAbout the team\n\nAbuse Operations is the front-line incident response and remediation function handling active product abuse and fraud impacting Stripe and its merchants. This multi-disciplinary group, spanning Incident Managers, Investigators, Forward Deployed Security Engineers, and Data Scientists, neutralizes active attacks, gathers requirements for operational tooling, and leads incidents. The team  works directly with impacted merchants to resolve technical incidents and policy abuse rapidly. Operating primarily across Eastern, Pacific and Western European time zones, these team members regularly coordinate with global stakeholders across the world.\n\nWhat you’ll do\n\nYou'll play a critical role in safeguarding our financial ecosystem by investigating high-risk accounts and identifying complex patterns of fraud during incidents. You will lead incident response for product abuse and fraud events, conducting deep-dive analyses to identify root causes. By collaborating cross-functionally, you will drive improvements that enhance our fraud detection and prevention strategies at scale. Your expertise will be essential in automating response processes through agentic approaches, allowing us to safeguard merchants and neutralize threats with speed and precision.\n\nResponsibilities\n\nInvestigate, mitigate, and remediate urgent fraud incidents (e.g., ATO, card testing), utilizing FT3-mapped detection and signals enrichment to reduce u
  ... (truncated for README)
```

### Failure behaviour

If a run finishes with nothing to deliver (bad input, unknown targets, blocked, everything filtered out) it **fails** with a clear status message instead of succeeding with an empty dataset. Per-target problems are listed in the `RUN_SUMMARY` key-value-store record.

### Legal & compliance notes

Data comes from the public, unauthenticated posting APIs that Greenhouse (`boards-api.greenhouse.io`), Lever (`api.lever.co`) and Ashby (`api.ashbyhq.com`) provide for publishing a company's open jobs. Only job-posting information that employers chose to publish is returned; no candidate or personal data.

- **Polite by design:** at least **1 second between requests to the same host** (the minimum cannot be lowered; this matches Lever's published `Crawl-delay: 1`). Requests identify themselves with a bot user-agent.
- **Attribution:** every record carries `sourceUrl` and `sourceBoardUrl`. Keep these links when you republish or display the data; the job text belongs to the employer.
- **Not covered:** SmartRecruiters is intentionally not supported because its API policy does not allow bulk extraction. Apple, LinkedIn and other job boards are not used.
- **Your responsibility:** use the data in line with the ATS providers' and employers' terms and applicable law (including privacy law).

### Takedown / contact

If you are an employer or ATS provider and want a posting or board excluded, or have a concern about this Actor, open an issue on this Actor's **Issues** tab in the Apify Store. Issues are read and handled by the AI agent that maintains this Actor on behalf of the owner, and requests to exclude a board or posting will be honored promptly.

### Limits

Boards that don't exist or have no open jobs return nothing (listed in `RUN_SUMMARY`). The delay between requests is at least 1 s per host, so large multi-board runs take correspondingly longer. Salary is only present where the employer publishes it (Ashby with compensation enabled; some Lever/Greenhouse boards).

### About this Actor

Built and maintained by an AI agent on behalf of the owner. Report issues through the Apify Actor's *Issues* tab; they are read and handled by the agent on the owner's behalf.

# Actor input Schema

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

Company board slugs or career-page URLs. Use 'greenhouse:stripe', 'lever:spotify', 'ashby:ashby' to target one ATS, a careers URL such as https://boards.greenhouse.io/airbnb or https://jobs.lever.co/spotify, or just a slug like 'stripe' to try every ATS selected below.

## `atsProviders` (type: `array`):

Only used for entries without an explicit ATS prefix or URL.

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

Keep only jobs whose title contains at least one of these words (case-insensitive). Empty = all jobs.

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

Drop jobs whose title contains any of these words.

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

Keep only jobs whose location text contains one of these strings, e.g. 'Remote', 'London', 'United States'.

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

Keep only jobs whose department or team contains one of these strings, e.g. 'Engineering'.

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

Keep only jobs the ATS flags as remote (or whose location says Remote).

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

0 disables the filter. Uses the first-published date when the ATS provides one.

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

Hard cap on jobs returned (and charged) in this run.

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

0 = no per-company limit.

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

Adds descriptionText and descriptionHtml. Price per job is the same.

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

Politeness delay per host. Minimum 1000 ms (Lever's robots.txt Crawl-delay is 1 s); lower values are raised to 1000.

## Actor input object example

```json
{
  "companies": [
    "greenhouse:stripe",
    "lever:spotify",
    "ashby:ashby"
  ],
  "atsProviders": [
    "greenhouse",
    "lever",
    "ashby"
  ],
  "keywords": [],
  "excludeKeywords": [],
  "locations": [],
  "departments": [],
  "remoteOnly": false,
  "postedWithinDays": 0,
  "maxItems": 1000,
  "maxJobsPerCompany": 0,
  "includeDescription": true,
  "requestDelayMs": 1000
}
```

# Actor output Schema

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

All job postings collected in this run (default dataset).

# 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": [
        "greenhouse:stripe",
        "lever:spotify",
        "ashby:ashby"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("apex_capricorn/ats-jobs-aggregator").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": [
        "greenhouse:stripe",
        "lever:spotify",
        "ashby:ashby",
    ] }

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

```

## MCP server setup

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

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/sXVduHZWOQAqfU80j/builds/eNmLHK6TUpqXyraib/openapi.json
