# Career Site Job Search: New Greenhouse & Lever Jobs (`humble-echidna/ats-job-search`) Actor

Search jobs across 6,000+ companies' Greenhouse and Lever career sites without naming them: by title, location, remote, company, department, salary and date (24h, 7d), with live descriptions and only-new mode. One index refreshed daily; every job checked on its board before you pay.

- **URL**: https://apify.com/humble-echidna/ats-job-search.md
- **Developed by:** [Michael Costa](https://apify.com/humble-echidna) (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 $1.40 / 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.
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

### What does Career Site Job Search do?

**Career Site Job Search** searches **jobs across 6,000 companies' career sites** on **Greenhouse and Lever** at
once, without naming the companies: by **job title, location, remote, company and posting date** (last 24 hours, 7
days...). It reads one index of about 210,000 open jobs, rebuilt daily from the companies' own public job boards, and
checks each job live on its board before you pay for it.

It is **not** a LinkedIn or Indeed scraper, and it doesn't cover every ATS: only companies whose careers page runs on
Greenhouse or Lever ([why](#which-companies-and-job-boards-does-it-cover)).

[Input fields](https://apify.com/humble-echidna/ats-job-search/input-schema) ·
[API](https://apify.com/humble-echidna/ats-job-search/api) ·
[Use it from Claude, ChatGPT or Cursor (MCP)](#can-i-use-career-site-job-search-from-an-ai-agent-mcp)

**Jump to:** [New jobs feed](#get-new-jobs-every-day-in-slack-email-or-a-webhook) ·
[Fields](#what-data-does-career-site-job-search-return) ·
[Price](#how-much-does-it-cost-to-search-jobs-across-company-career-sites) ·
[How to use](#how-to-search-jobs-across-company-career-sites) ·
[Coverage](#which-companies-and-job-boards-does-it-cover) ·
[Input](#input) · [Output](#output) ·
[AI agents (MCP)](#can-i-use-career-site-job-search-from-an-ai-agent-mcp) · [Limits](#limits) · [FAQ](#faq)

**Try it in one click:** the input comes pre-filled with `software engineer`, posted in the last 7 days, 20 jobs.
That's 20 jobs, or about $0.04 (20 × $0.002, plus $0.00005 for the run start). **Then replace it with what you
actually want.**

### Get new jobs every day, in Slack, email or a webhook

With **Only new jobs since the last run** on, each run returns (and charges for) only the jobs that search hasn't
returned before. A run with nothing new costs only the $0.00005 start fee.

1. Set your search (for example **Job title keywords** `data engineer`, **Locations** `remote`, **Posted within**
   `7d`), turn on **Only new jobs since the last run** (`"onlyNewJobs": true`), and click **Start**. This first run
   returns the matching jobs and is the baseline.
2. Click **Save as a new task** (top right of the actor page). The memory is kept in a store in your own account,
   one per combination of filters, so the task keeps comparing with its own last run and other searches never hide
   its jobs.
3. In Apify Console, open **Schedules**, click **Create new**, set how often in **Schedule setup** (daily is enough:
   the index is rebuilt once a day), then **Add** your task.
4. On the task, open the **Integrations** tab and pick where the new jobs go:
   - **Slack**: click **Configure**, sign in, pick the workspace and channel, and the "run succeeded" event. A
     useful message: `{{resource.statusMessage}}` and a link,
     `<https://console.apify.com/storage/datasets/{{resource.defaultDatasetId}}|new jobs>`.
   - **Gmail**: click **Connect with Google**, set the subject and body, and attach the dataset. It sends after each
     successful run.
   - **HTTP webhook**: event `ACTOR.RUN.SUCCEEDED`, your URL. Apify POSTs `{"eventType": ..., "resource": {...}}`;
     `resource.defaultDatasetId` is the run's dataset, and
     `GET https://api.apify.com/v2/datasets/<defaultDatasetId>/items?format=json` (with your API token) returns the
     new jobs.

Apify's integrations fire after every successful run, including quiet ones: a quiet run's dataset is empty. If a run
stops at **Max jobs per run** before it has returned everything new, the next run carries on where it stopped.

### What data does Career Site Job Search return?

| Field | Example | Notes |
|---|---|---|
| `title` | `Senior Data Engineer` | As the company wrote it |
| `companyName` | `Stripe` | `company` is the board id (`stripe`) |
| `location`, `locations` | `San Francisco, CA` | The company's own text; every location for multi-site jobs |
| `remote`, `workplaceType` | `true`, `remote` | `remote` / `hybrid` / `onsite`; `null` when the board doesn't say |
| `employmentType` | `FULL_TIME` | Lever only; `null` on Greenhouse |
| `postedAt` | `2026-10-08T14:02:11Z` | The board's own posting date |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | `150000`, `190000`, `USD`, `YEAR` | From the board's salary field, or a pay range in the description; `null` when neither has one |
| `description` | `About the role ...` | Plain text, read live; `null` with descriptions off |
| `url`, `applyUrl` | `https://job-boards.greenhouse.io/...` | The job page and the application page |
| `firstSeenAt` | `2026-10-07T23:06:43Z` | When the daily index first saw the job |
| `verifiedAt` | `2026-10-09T08:12:40Z` | When this run found it still open on its board; `null` if the board couldn't be read |

The fields match [Company Career Page Jobs Scraper](https://apify.com/humble-echidna/ats-jobs), so you can go from
"search all companies" to "monitor these companies" without re-mapping. The full list is under [Output](#output).

### How much does it cost to search jobs across company career sites?

You pay per job returned: **$2.00 per 1,000 jobs** ($0.002 a job), plus $0.00005 each time a run starts. Jobs that
closed since the index was built, or no longer match after the live check, are dropped before they're charged.

- **The pre-filled example:** 20 jobs × $2.00/1,000 = $0.04, plus the start fee.
- **A month, for example:** a daily "new jobs" feed for one search that finds 30 new jobs a day ≈ 900 jobs ≈
  **$1.80**, plus 30 start fees ($0.0015).
- **Caps:** **Max jobs per run** in the input (default 100), and **Maximum cost per run** in the run options. The run
  stops cleanly at whichever comes first, and stops reading boards as soon as the limit is covered.

**Never charged:** jobs closed since the index was built, jobs a filter drops, jobs an only-new search returned
before, and a run with nothing new beyond the start fee.

### How to search jobs across company career sites

1. Open Career Site Job Search and click **Try for free** (or **Start** if you're signed in).
2. Fill in **Job title keywords** (`software engineer`, `account executive`), and if you like **Locations**
   (`Berlin`, `remote`) and **Posted within** (`24h`, `7d`).
3. Optional: narrow it down by company, department, employment type, salary or platform, or turn off descriptions
   for a faster run with fields from the index only.
4. Click **Start**, then open the **Output** tab and export as JSON, CSV or Excel.

### Which companies and job boards does it cover?

**6,000 companies with open jobs, about 210,000 jobs** (index of 2026-10-08: Greenhouse 4,485 companies /
161,718 jobs, Lever 1,530 / 48,261). Mostly tech, startups and fast-growing companies, worldwide, in the
language each company writes in.

- The board list starts from the open, MIT-licensed company lists of
  [job-board-aggregator](https://github.com/Feashliaa/job-board-aggregator) by Riley Dorrington (12,701 Greenhouse
  and Lever company boards). Boards with open jobs are checked daily; boards with none (or that no longer exist)
  are checked weekly and come back as soon as they post a job.
- **Greenhouse and Lever only.** Both publish their job boards for anyone to read: Greenhouse's docs say "Job Board
  data is publicly available", and Lever's say published postings "may be scraped by third parties". Other ATSs
  either aren't cleared for a stored, shared index (Ashby routes job aggregators through an opt-in partner program)
  or forbid automated access (Workday, iCIMS, Taleo and others). See the [FAQ](#why-isnt-my-company-or-workday-ashby-linkedin-in-the-results).
- Need a company that isn't here, or another ATS (Ashby, Recruitee, Personio, Teamtailor)? Name the company in
  [Company Career Page Jobs Scraper](https://apify.com/humble-echidna/ats-jobs), which reads it live.

### Example: software engineer jobs posted this week

The pre-filled input:

```json
{"titleKeywords": ["software engineer"], "postedWithin": "7d", "maxJobs": 20}
```

On Apify on 2026-10-09 (index built 2026-10-08 23:06 UTC), it matched 586 jobs in the index, read 16 companies'
boards live and returned the 20 newest, from 16 companies, in 15 s: $0.04 plus the start fee. A few of them:

| Title | Company | Location | Posted | Salary |
|---|---|---|---|---|
| AI Security Software Engineer (Starshield) | SpaceX | Washington, DC | 2026-10-08 | |
| Embedded Software Engineer, Platform (Starshield) | SpaceX | Hawthorne, CA | 2026-10-08 | |
| Software Engineer II, Full Stack (Digital Products - Service) | Scout Motors | Fremont, California, United States | 2026-10-08 | $121,000 - $148,500 |
| Software Engineer, AI/ML | PlayStation Global | United States, San Diego, CA | 2026-10-08 | $150,000—$225,000 USD |
| Senior Software Engineer | Rocket Lab Corporation | Auckland, NZ | 2026-10-08 | |

### Input

| Field | What it does |
|---|---|
| **Job title keywords** (`titleKeywords`) | Jobs whose title contains any of these words or phrases. Matching ignores case and starts at a word: `engineer` also finds Engineering. |
| Exclude title keywords (`excludeTitleKeywords`) | Drop titles with any of these (`senior`, `intern`). |
| Locations / Exclude locations (`locations`, `excludeLocations`) | The company's own location text: try the city and the country. `remote` also keeps jobs marked remote. |
| Remote only (`remoteOnly`) | Only jobs the board marks as remote. |
| Posted within (`postedWithin`) | `24h`, `3d`, `7d` (default), `30d` or `any`. On Apify's Free plan, `30d` and `any` search the last 7 days (see [Limits](#limits)). |
| Only new jobs since the last run (`onlyNewJobs`) | Return only jobs this search hasn't returned before. |
| Companies / Exclude companies (`companies`, `excludeCompanies`) | By company name or board id. |
| Description keywords / Exclude (`descriptionKeywords`, `excludeDescriptionKeywords`) | Checked on the live description (`python`, `visa sponsorship`). |
| Departments (`departments`) | Department or team (Lever boards only). |
| Employment types (`employmentTypes`) | `FULL_TIME`, `PART_TIME`, `CONTRACT`, `TEMPORARY`, `INTERNSHIP`, `VOLUNTEER` (Lever boards only). |
| Only jobs with a salary (`hasSalary`) | The board's salary field, or a pay range in the description. |
| Job board platforms (`platforms`) | `greenhouse`, `lever`; empty = both. |
| Include descriptions (`includeDescription`) | On (default): read each matching board live for descriptions and the open check. Off: index fields only, faster. |
| Max jobs per run (`maxJobs`) | Newest first; default 100, maximum 10,000. |
| Max jobs per company (`maxJobsPerCompany`) | So one big employer doesn't fill the run. |

```json
{
  "titleKeywords": ["data engineer", "analytics engineer"],
  "excludeTitleKeywords": ["intern"],
  "locations": ["remote", "New York"],
  "postedWithin": "7d",
  "onlyNewJobs": true,
  "maxJobs": 100
}
```

### Output

Every job has the same fields. Fields the board doesn't publish are `null`.

One job from the example run (real output; description shortened):

```json
{
  "id": "greenhouse:scoutmotors:5260681007",
  "platform": "greenhouse",
  "company": "scoutmotors",
  "companyName": "Scout Motors",
  "title": "Software Engineer II, Full Stack (Digital Products - Service)",
  "department": "Commercial Operations",
  "team": null,
  "location": "Fremont, California, United States",
  "locations": ["Fremont, California, United States"],
  "country": null,
  "remote": false,
  "workplaceType": null,
  "employmentType": null,
  "postedAt": "2026-10-08T22:45:24Z",
  "updatedAt": "2026-10-08T22:47:15Z",
  "url": "https://job-boards.greenhouse.io/scoutmotors/jobs/5260681007",
  "applyUrl": "https://job-boards.greenhouse.io/scoutmotors/jobs/5260681007",
  "salaryMin": 121000,
  "salaryMax": 148500,
  "salaryCurrency": "USD",
  "salaryPeriod": "YEAR",
  "salaryText": "$121,000 - $148,500",
  "salarySource": "description",
  "description": "Here at Scout Motors, we're carrying forward the heritage of one of the most iconic American vehicles in history. A vehicle dating back to 1960. One that ...",
  "firstSeenAt": "2026-10-08T23:06:43Z",
  "verifiedAt": "2026-10-09T00:40:44Z",
  "indexedAt": "2026-10-08T23:06:43Z",
  "scrapedAt": "2026-10-09T00:40:44Z"
}
```

`id` is `platform:company:job id` and stable across runs, so you can use it to deduplicate. Jobs come newest first.
The run's `RUN_STATS` record says when the index was built, how many jobs matched, how many closed since the index
was built (`closedSinceIndex`), and any board that couldn't be read live, with the reason. Jobs whose board gives no
posting date (a few Greenhouse boards) come last.

### Run it on a schedule, or from your own code

1. Save your input as a [task](https://docs.apify.com/platform/actors/running/tasks) (**Save as a new task**, top right
   of the actor page) and add it to a [schedule](https://docs.apify.com/platform/schedules) (Console → Schedules →
   **Create new**).
2. Collect results: download the dataset as JSON, CSV or Excel; fetch the latest run's results from the
   [API](https://apify.com/humble-echidna/ats-job-search/api)
   (`GET https://api.apify.com/v2/actor-tasks/<task id>/runs/last/dataset/items?status=SUCCEEDED&format=csv`, with
   your API token); let a [webhook](https://docs.apify.com/platform/integrations/webhooks) tell your system when a
   run succeeds; or connect it to Make, Zapier or n8n through
   [Apify's integrations](https://docs.apify.com/platform/integrations).

#### Can I use Career Site Job Search from an AI agent (MCP)?

Yes, through [Apify's MCP server](https://docs.apify.com/platform/integrations/mcp), from Claude, ChatGPT, Cursor or
any other MCP client. Add this to your client's MCP configuration (or let the agent find it with the server's actor
search); your client signs you in to Apify:

```json
{
  "mcpServers": {
    "apify": {
      "url": "https://mcp.apify.com?tools=humble-echidna/ats-job-search"
    }
  }
}
```

To use an [Apify API token](https://console.apify.com/settings/integrations) instead of signing in, add
`"headers": {"Authorization": "Bearer <APIFY_TOKEN>"}` next to `url`.

An agent should pass the search and a small cap, e.g. `{"titleKeywords": ["product designer"], "locations": ["London"], "postedWithin": "7d", "maxJobs": 20}`, and `"includeDescription": false` when it only needs titles and
links.

### Who it's for

Job boards and newsletters that publish fresh tech and startup roles every day, recruiters and sourcers watching who
is hiring for a role, and job seekers who want one daily feed across thousands of companies instead of checking each
careers page.

### Why this one?

- **Checked before you pay.** With descriptions on (the default), every job is re-read on its own board in the same
  run: one that closed since the index was built is dropped, not charged.
- **Only new jobs, per search.** A daily feed returns each job once, with the memory in your own account.
- **$2.00 per 1,000 jobs**, with the same fields as Company Career Page Jobs Scraper.
- **Polite and safe.** The index is refreshed with conditional requests (an unchanged board answers with an empty
  304\), with an honest User-Agent (`HumbleEchidnaApify`), each site's robots.txt and Lever's crawl delay.

### Limits

- **Two platforms, 6,000 companies.** Companies on other ATSs, or on Greenhouse and Lever but not in the board
  list, aren't in the index (see [coverage](#which-companies-and-job-boards-does-it-cover)).
- **Daily index.** A job posted after the last rebuild appears in the next one, so `24h` means "posted in the last 24
  hours and already indexed". There is no 1-hour window.
- **Greenhouse's job list has no departments or employment types**, so those filters keep only Lever jobs.
- Description keywords are checked on each candidate company's live board. A run stops once 400 companies read live
  gave it no job (closed, or no keyword match), so combine them with title keywords or a short window. The status
  message says when a run stopped there.
- **Free plan: the last 7 days.** On Apify's Free plan, `30d` and `any` search jobs posted in the last 7 days, and
  the status message says so. Any paid Apify plan searches 30 days or any time.
- Locations are free text as each company writes them; there is no geographic radius search or country code mapping.
- No AI enrichment (seniority, skills, visa) and no LinkedIn company data.

### FAQ

#### Is it legal to search jobs across company career sites?

It reads only the job boards Greenhouse and Lever publish for anyone to read: Greenhouse's Job Board API ("Job Board
data is publicly available, so authentication is not required for any GET endpoints") and Lever's postings API
("These jobs may be scraped by third parties"). Neither platform's published terms restrict reading its public job
boards; their terms of service are contracts with their customers. No login is used. It collects job postings only: no recruiter names,
emails or applicant data.

#### How fresh is the data?

The index is rebuilt once a day; each run's `RUN_STATS` (`indexBuiltAt`) and status message say when. With
descriptions on, every job you get was also found open on its board during your run (`verifiedAt`).

#### Why isn't my company (or Workday, Ashby, LinkedIn) in the results?

Only companies whose careers page runs on Greenhouse or Lever and that are in the board list are indexed. Workday,
iCIMS, Taleo, SmartRecruiters and others forbid automated access in their terms or robots.txt. Ashby's public API is
documented for a company's own careers page, and Ashby lets each customer choose which job aggregators get its jobs,
so it isn't in a shared index. To track named companies on six ATSs (Ashby included), use
[Company Career Page Jobs Scraper](https://apify.com/humble-echidna/ats-jobs).

#### Why did a search return nothing, or fewer jobs than expected?

Check **Posted within** first (the default is 7 days), then the keywords: they match at the start of a word, so
`ops` finds "Ops Manager" and "DevOps" doesn't match `ops`. `RUN_STATS` says how many jobs matched in the index
(`matched`) and how many closed since it was built (`closedSinceIndex`).

#### Can I get only new jobs since my last run?

Yes: turn on **Only new jobs since the last run** and schedule the search
([how](#get-new-jobs-every-day-in-slack-email-or-a-webhook)). Each combination of filters has its own memory in your
account.

#### How is this different from a job database like fantastic.jobs, Hirebase or Jobo?

Those index far more sources (millions of jobs, dozens of ATSs, AI-extracted fields and company data) at $3-12 per
1,000 jobs on Apify's Starter plan. This one covers Greenhouse and Lever only, at $2.00 per 1,000, and checks every
job on its board before charging. Pick it when your audience is tech and startup roles and you want verified, fresh
links at a low price.

### Related actors

| Actor | Use it when |
|---|---|
| [Company Career Page Jobs Scraper](https://apify.com/humble-echidna/ats-jobs) | You know the companies: all their jobs on six ATSs, with closed and changed jobs |
| [Greenhouse Jobs Scraper](https://apify.com/humble-echidna/greenhouse-jobs) | Named companies on Greenhouse only |
| [Lever Jobs Scraper](https://apify.com/humble-echidna/lever-jobs) | Named companies on Lever only |
| [Remote Jobs Scraper](https://apify.com/humble-echidna/remote-jobs) | Remote job boards: We Work Remotely, Remote OK and Python.org Jobs |

### Feedback and support

Found a bug, or need a field, filter or company that isn't here? Open an issue on the **Issues** tab with the input
you used.

### Versions

Current version: **0.1**. See the Changelog tab for what changed in each version.

# Changelog

This Actor's version history is a separate document: https://apify.com/humble-echidna/ats-job-search/changelog.md

# Actor input Schema

## `titleKeywords` (type: `array`):

Keep jobs whose title contains any of these words or phrases, e.g. `software engineer`, `data scientist`, `product manager`. Matching ignores case and starts at a word: `engineer` also finds Engineering, `ai` finds AI Engineer but not Chair. Empty: any title.

## `excludeTitleKeywords` (type: `array`):

Drop jobs whose title contains any of these, e.g. `senior`, `intern`, `manager`. Same matching as the title keywords. Empty: drop nothing.

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

Keep jobs whose location names any of these, e.g. `London`, `New York`, `Germany`, `remote`. `remote` also keeps jobs the board marks as remote. Locations are the company's own text, so try the city and the country. Empty: anywhere.

## `excludeLocations` (type: `array`):

Drop jobs whose location names any of these, e.g. `India`, `Hybrid`. Empty: drop nothing.

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

Only jobs the board marks as remote (Lever's workplace type, or a location that says remote). Default: off.

## `postedWithin` (type: `string`):

Only jobs posted in this window: `24h`, `3d`, `7d` (the default), `30d` or `any`. Uses the board's own posting date, or when the index first saw the job if the board gives none. The index is rebuilt daily. On Apify's Free plan, `30d` and `any` search the last 7 days; any paid plan searches 30 days or any time.

## `onlyNewJobs` (type: `boolean`):

Return only jobs this same search hasn't returned before, for a scheduled feed. The memory is kept in your own account, one per combination of filters, so different searches never hide each other's jobs. Default: off.

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

Keep only jobs at companies whose name or board id contains any of these, e.g. `stripe`, `notion`. Empty: every company in the index.

## `excludeCompanies` (type: `array`):

Drop jobs at companies whose name or board id contains any of these, e.g. a recruiting agency or your own company. Empty: drop nothing.

## `descriptionKeywords` (type: `array`):

Keep jobs whose description contains any of these, e.g. `python`, `kubernetes`, `visa sponsorship`. Descriptions are read live from each matching company's board, so combine this with title keywords or a short window to keep the run fast. Empty: no description filter.

## `excludeDescriptionKeywords` (type: `array`):

Drop jobs whose description contains any of these, e.g. `clearance`, `on-site only`. Read live, like the description keywords. Empty: drop nothing.

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

Keep jobs whose department or team contains any of these, e.g. `engineering`, `sales`. Greenhouse's list doesn't name departments, so this filter keeps only Lever jobs. Empty: any department.

## `employmentTypes` (type: `array`):

Keep only these types: FULL_TIME, PART_TIME, CONTRACT, TEMPORARY, INTERNSHIP, VOLUNTEER. Only Lever boards state a type, so this filter leaves out Greenhouse jobs. Empty: any type.

## `hasSalary` (type: `boolean`):

Only jobs that publish pay: the board's salary range, or, with descriptions on, a pay range written in the description. Default: off.

## `platforms` (type: `array`):

Search only these platforms: `greenhouse`, `lever`. Empty: both.

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

Read each matching company's board live for the full job description. This also drops jobs closed since the index was built, before anything is charged, and fills salary from the description where the board has no salary field. Off: faster, fields from the index only. Default: on.

## `maxJobs` (type: `integer`):

Stop after this many jobs in total, newest first, e.g. 20. Minimum 1, maximum 10000, default 100. The run also stops cleanly at the maximum cost per run you set in the run options, whichever comes first.

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

At most this many jobs from any one company, e.g. 3, so one big employer doesn't fill the run. Minimum 1; leave empty (the default) for no limit.

## Actor input object example

```json
{
  "titleKeywords": [
    "software engineer"
  ],
  "remoteOnly": false,
  "postedWithin": "7d",
  "onlyNewJobs": false,
  "hasSalary": false,
  "includeDescription": true,
  "maxJobs": 20
}
```

# Actor output Schema

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

No description

## `runStats` (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 = {
    "titleKeywords": [
        "software engineer"
    ],
    "maxJobs": 20
};

// Run the Actor and wait for it to finish
const run = await client.actor("humble-echidna/ats-job-search").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 = {
    "titleKeywords": ["software engineer"],
    "maxJobs": 20,
}

# Run the Actor and wait for it to finish
run = client.actor("humble-echidna/ats-job-search").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 '{
  "titleKeywords": [
    "software engineer"
  ],
  "maxJobs": 20
}' |
apify call humble-echidna/ats-job-search --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,humble-echidna/ats-job-search"
        }
    }
}
```

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/gS8Iy2RzF0aCx99AH/builds/qsLrmmgOhXzXQFRXg/openapi.json
