# Tech Jobs Aggregator — Greenhouse, Ashby & Lever in one feed (`vincentkirui/tech-jobs-aggregator`) Actor

Aggregate live job postings across companies' public ATS boards (Greenhouse, Ashby, Lever) into one normalized, deduped feed. Auto-detects each company's ATS. Filter by keyword, location, remote. For recruiters, sales prospecting (hiring = buying signal) and talent intelligence.

- **URL**: https://apify.com/vincentkirui/tech-jobs-aggregator.md
- **Developed by:** [Vincent Kirui](https://apify.com/vincentkirui) (community)
- **Categories:**
- **Stats:** 2 total users, 1 monthly users, 83.3% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.
Actors are written with capital "A".

## 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.
The best way to integrate Actors is as follows.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — the [REST API](https://docs.apify.com/api/v2.md).

For usage examples, see the [API](#api) section below.

For more details, see Apify documentation as [Markdown index](https://docs.apify.com/llms.txt) and [Markdown full-text](https://docs.apify.com/llms-full.txt).

# README

## Tech Jobs Aggregator — Greenhouse, Ashby & Lever in one feed

Aggregate live job postings across companies' public **ATS boards** — Greenhouse, Ashby, and
Lever — into **one normalized, deduped feed**. No login, no anti-bot: these boards are
published by companies specifically to be consumed by aggregators. The value is the
aggregation the raw endpoints don't give you.

### Why this beats a single-board scraper

- **One schema across three ATS shapes** — company, title, location, remote, team, apply URL, posted date, description, all normalized.
- **Auto-detects the ATS** — give a company slug (e.g. `notion`) and it figures out whether they use Greenhouse, Ashby, or Lever. You don't need to know.
- **Built-in company directory** so `search` works out of the box across well-known tech companies; add your own with `companies`.
- **Filter + dedupe** — keyword, location, remote-only, de-duplicated across boards.

### Modes

| Mode | What it does |
|---|---|
| **Search** | Filter jobs by keyword / location / remote across the built-in directory (+ any companies you add) |
| **Company** | Pull *all* live jobs for the specific companies you list (ATS auto-detected) |

### Who it's for

Recruiters and talent-intelligence tools; **sales prospecting** (a company hiring is a growth
& buying signal); job-board builders; and AI agents — as an MCP tool answering *"who's hiring
for backend roles?"* or *"is {company} hiring?"*.

### Output

Flat JSON rows: `company`, `ats`, `title`, `location`, `remote`, `team`, `url`,
`published_at`, `description`.

### Input examples

```json
{ "mode": "search", "keywords": ["engineer","backend"], "remoteOnly": true, "maxItems": 500 }
```

```json
{ "mode": "company", "companies": ["stripe", "openai", "gopuff"], "maxItems": 1000 }
```

A slug is the last part of a careers URL: `boards.greenhouse.io/stripe` → `stripe`,
`jobs.ashbyhq.com/openai` → `openai`, `jobs.lever.co/gopuff` → `gopuff`.

### Use cases

- **Recruiting & talent intelligence** — a live feed of who is hiring, for which roles, where. Track competitors' engineering headcount growth from their own job boards.
- **Sales prospecting & lead generation** — a company posting backend/DevOps roles is a buying signal for dev tools, cloud services and recruiting agencies. Export hiring companies to CSV for outreach.
- **Job boards & newsletters** — power a niche remote-jobs board or a weekly "who's hiring" newsletter without writing three scrapers for Greenhouse, Ashby and Lever.
- **Market research** — salary-band, tech-stack and remote-work trends from thousands of live postings.
- **AI agents** — call this actor as an MCP tool so an agent can answer "is Stripe hiring engineers?" with live data.

### FAQ

**How do I get jobs from the Greenhouse job board API?**
Every Greenhouse board is public at `boards.greenhouse.io/{company}`. This actor reads those public endpoints for you, plus Ashby and Lever, and returns one normalized JSON schema — no API key required.

**Can I scrape Lever and Ashby jobs without an API key?**
Yes. Companies publish these boards to be read. Give the actor a company slug (`jobs.lever.co/gopuff` → `gopuff`) and it auto-detects the ATS.

**How is this different from scraping LinkedIn or Indeed?**
LinkedIn and Indeed aggressively block scrapers and their listings are ad-mixed. ATS boards are the *source of truth* the aggregators themselves read — cleaner data, zero anti-bot risk.

**Can I export the jobs to CSV or Excel?**
Yes — every run's dataset downloads as CSV, Excel, JSON or XML from the Apify console or API, ready for spreadsheets or your ATS.

**How do I keep a job feed continuously updated?**
Schedule the actor (e.g. every 6 hours) in Apify → Schedules, and read the dataset from your app, Zapier/Make, or a webhook.

**Does it find remote-only jobs?**
Set `"remoteOnly": true` in search mode to keep only remote-friendly postings across all companies.

### Legal

Reads companies' public ATS job-board APIs, which are published for aggregation. No login,
no circumvention. Respect rate limits; link back to the original posting when republishing.

### Pricing

Pay-per-event: a small actor-start fee plus a per-job charge — you pay for exactly the jobs
you pull.

# Actor input Schema

## `mode` (type: `string`):

search = filter jobs across a directory of companies (+ any you add); company = all jobs for the companies you list

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

Company ATS slugs, e.g. stripe, openai, gopuff. The ATS is auto-detected; a slug is the last part of a careers URL (boards.greenhouse.io/SLUG, jobs.ashbyhq.com/SLUG, jobs.lever.co/SLUG). In search mode these are added to the built-in directory.

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

Keep only jobs whose title/team contains any of these (e.g. engineer, product, sales).

## `location` (type: `string`):

Keep only jobs whose location contains this text (e.g. London, New York, Remote).

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

Keep only jobs flagged remote.

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

Stop after this many jobs total.

## Actor input object example

```json
{
  "mode": "search",
  "companies": [
    "stripe",
    "openai",
    "notion"
  ],
  "keywords": [
    "engineer",
    "backend"
  ],
  "remoteOnly": false,
  "maxItems": 500
}
```

# Actor output Schema

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

Aggregated, normalized job postings in the 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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("vincentkirui/tech-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 = {}

# Run the Actor and wait for it to finish
run = client.actor("vincentkirui/tech-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 '{}' |
apify call vincentkirui/tech-jobs-aggregator --silent --output-dataset

```

## MCP server setup

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