# Career Site Job Search — Verified Greenhouse & Lever Boards (`hermeskd/ats-job-search`) Actor

Search open jobs in the Hermes directory of verified company career sites on Greenhouse and Lever (27 boards, 5,619 postings at its 2026-10-26 build) by keyword, location, country, remote and department; every result is checked live on the employer's board. $0.002 a job plus $0.01 a search.

- **URL**: https://apify.com/hermeskd/ats-job-search.md
- **Developed by:** [Logan Parker](https://apify.com/hermeskd) (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

from $1.60 / 1,000 job matcheds

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

Search open jobs in the Hermes directory of verified company career sites on Greenhouse and Lever — 27 boards and 5,619 postings at its 2026-10-26 build, not every company board — by keyword, location, country, remote, department, company and recency, and get back only postings confirmed open on the employer's own board at call time, never a stale repost. For job-search tools, recruiters and AI agents that need current roles from the source. $0.002 a job plus $0.01 a search; a search whose live checks all fail costs nothing. Not affiliated with Greenhouse or Lever.

### Example result

A job record from the production image's run of the smoke input against the live source (2026-10-26T12:48:43Z). The run's first record also carries `directory` (the Hermes directory's boards, postings and build date) and the last record is a free summary: candidates, boards read, closed postings dropped, postings no longer matching, returned.

```json
{
  "type": "job",
  "source": "greenhouse",
  "board": "stripe",
  "region": "global",
  "company": "Stripe",
  "jobId": "8202299",
  "title": "Software Engineer, New Grad",
  "departments": [
    "5112 General University"
  ],
  "offices": [
    "TW-Taipei City"
  ],
  "location": {
    "raw": "Taiwan",
    "city": null,
    "region": null,
    "country": "TW",
    "remote": false
  },
  "salary": null,
  "postedAt": "2026-10-23T03:22:57Z",
  "updatedAt": "2026-10-23T21:54:30Z",
  "descriptionMarkdown": null,
  "applyUrl": "https://stripe.com/jobs/search?gh_jid=8202299",
  "sourceUrl": "https://job-boards.greenhouse.io/stripe/jobs/8202299",
  "matchedTerms": [
    "engineer"
  ],
  "ok": true
}
```

### How to use it

Start a run in Apify Console, by API or from an agent with an input like this one — it is the input Apify runs every day to test this Actor:

```json
{
  "query": [
    "engineer"
  ],
  "maxResults": 10
}
```

| Field | Type | Meaning |
|---|---|---|
| `query` | array | Keywords; a posting matches when its title or a department contains any of them (case-insensitive words or phrases); 1–50. |
| `locations` | array | Return only postings whose location text, city, region or country matches any of these. |
| `countries` | array | Return only postings whose stated location is in one of these countries (ISO 3166-1 alpha-2 codes). |
| `remoteOnly` | boolean | Return only postings the board marks remote. |
| `departments` | array | Return only postings in a department (or Lever team) containing any of these words. |
| `companies` | array | Search only these companies' boards (company names or board tokens); 1–100. |
| `postedWithinDays` | integer | Return only postings first published or created in the last N days; 1–3,650, default 30. |
| `maxResults` | integer | Most confirmed matches returned, newest first; 1–1,000. |
| `includeDescription` | boolean | Return each posting's description as redacted Markdown. |

### Events and prices

| Event | Title | Charged when | FREE / BRONZE | SILVER | GOLD / PLATINUM / DIAMOND |
|---|---|---|---|---|---|
| `job-matched` | Job matched | One matching posting returned. | $0.002 | $0.0018 | $0.0016 |
| `search-run` | Search run | One search across the directory (once per run). | $0.01 | $0.009 | $0.008 |

Worked cost: a search returning 25 jobs costs 25 × $0.002 + $0.01 = $0.06 at the FREE and BRONZE price, $0.054 on SILVER and $0.048 on GOLD and above, plus the actor-start event.

Platform usage is not passed through. Apify's automatic actor-start event remains $0.00005 per started GB (one GB or less counts once). The synthetic dataset-item event is absent. Failure records and the free summary records are never charged; when the run's maximum total charge is reached, further work stops and the rest gets uncharged `charge_limit_reached` records. Work completed before an abort is settled.

### Call it from an agent

Through Apify's MCP server (https://mcp.apify.com) use `call-actor`:

```json
{
  "actor": "hermeskd/ats-job-search",
  "input": {
    "query": [
      "engineer"
    ],
    "maxResults": 10
  },
  "callOptions": {
    "maxTotalChargeUsd": 0.05,
    "timeout": 600
  },
  "waitSecs": 30
}
```

Then call `get-dataset-items` with the returned defaultDatasetId. Dedicated tool URL: https://mcp.apify.com?tools=hermeskd/ats-job-search

### Output fields

| Field | Meaning |
|---|---|
| `type` | job: one matching posting, confirmed open on its board at call time; summary: the last record, free (counts and coverage). |
| `source` | The applicant-tracking system the posting lives on. |
| `board` | Greenhouse board token or Lever site name. |
| `region` | Lever instance (global or eu); global for Greenhouse. |
| `company` | Company as the board names it (Greenhouse) or the site name (Lever). |
| `jobId` | The posting id on its board. |
| `title` | Job title. |
| `departments` | Departments (Greenhouse) or department and team (Lever). |
| `offices` | Greenhouse office names; empty for Lever. |
| `location` | Location parsed from the source text: raw text, and city, region (US state code) and ISO 3166-1 alpha-2 country only when the text states them unambiguously; remote when the source says so. |
| `salary` | Pay range only when the source states one; never inferred. |
| `postedAt` | First published (Greenhouse) or created (Lever), UTC ISO 8601. |
| `updatedAt` | Last updated (Greenhouse); null for Lever. |
| `descriptionMarkdown` | Description as Markdown with emails and phone numbers redacted; null unless includeDescription is true. |
| `applyUrl` | Where the company sends applicants. |
| `sourceUrl` | The posting's page on the public board. |
| `matchedTerms` | The query terms the posting matched. |
| `directory` | The Hermes board directory this search used, on the run's first record and on the summary: boards, postings, build date, build seconds, and whether the published store or the snapshot baked into the image was read. |
| `candidates` | Summary: postings in the directory's index that matched the query and filters. |
| `boardsWithCandidates` | Summary: boards those candidates are on. |
| `boardsRead` | Summary: boards read live to confirm candidates. |
| `boardsFailed` | Summary: live board reads that failed. |
| `closedDropped` | Summary: candidates no longer on their board (closed since the index was built), dropped. |
| `noLongerMatching` | Summary: candidates still open whose live posting no longer matches, dropped. |
| `returnedJobs` | Summary: confirmed matches returned. |
| `stoppedAt` | Summary: why the search stopped before reading every candidate board (maxResults is not listed; charge limit, run deadline or the board-read limit), or null. |
| `failedBoards` | Summary: the boards whose live read failed, with the code (first 50). |
| `ok` | True for every confirmed match and for the summary of a search that ran. |
| `error` | Failure, never charged. |

### Limits and run time

1–1,000 results (`maxResults`, default 100), newest first; `postedWithinDays` defaults to 30. Candidates come from the directory's postings index; their boards are read live in order until `maxResults` confirmed matches are returned (at most 200 board reads a run, one request a second per host). The directory is the published Hermes store when it can be read, else the snapshot baked into the image — the `directory` object says which, with its board and posting counts and build date (the snapshot of 2026-10-26: 27 verified boards, 5,619 postings, two-thirds of them one Lever site's listings). A directory built longer ago than the search's `postedWithinDays` window holds no posting of the window: the search is not run, and a free `directory_stale` record says so. `search-run` is charged once: with the first confirmed match, or with the summary of a successful search that found nothing. A missing directory, input the Actor cannot use, or a search whose every live board read failed charges nothing. The smoke input (ten results) ran in 4.0 seconds end to end in the production image on 2026-10-26; the default run timeout is 600 seconds. Cold platform time, cost and the smallest passing memory are measured by the deploy.

### Errors

| Code | Meaning |
|---|---|
| `directory_unavailable` | Neither the published directory nor the snapshot baked into the image could be read; nothing is charged. |
| `directory_stale` | The directory was built longer ago than the search's `postedWithinDays` window, so it can hold no posting of the window; the search is not run and nothing is charged. The message states the directory's age. |
| `rate_limited` | Every live board read was refused with HTTP 429; nothing was charged. |
| `source_schema_changed` | The source's response no longer has the verified shape; the run fails loudly when every input does. |
| `download_failed` | Every live board read failed; nothing was charged. |
| `robots_disallowed` | robots.txt forbids fetching the URL; no request was made to it. |
| `blocked_host` | The host is on the deny-list or resolves to a private or local address; no request was made. |
| `timeout` | The input did not finish within the run's time budget. |
| `invalid_input` | The run input passed the input schema but cannot be used; the message names the field. |
| `internal_error` | Unexpected failure; the message carries the error class. |
| `charge_limit_reached` | The run reached its maximum total charge; this input was not processed. |

No failure record is charged. A run fails only when every input failed on the Actor's side (`internal_error`, `timeout`, `source_schema_changed`); caller-side failures and mixtures leave the run SUCCEEDED.

### Sources and terms

Two feeds, through the Hermes board directory. Greenhouse Job Board API (`boards-api.greenhouse.io/v1/boards/{token}/jobs`). Greenhouse's documentation, read 2026-10-26 on docs.greenhouse.io: "Job Board data is publicly available, so authentication is not required for any GET endpoints." Only the application POST needs a key, and no Hermes Actor calls it. The API host's robots.txt (read 2026-10-26) disallows only `/embed/`. Lever Postings API (`api.lever.co/v0/postings/{site}?mode=json`, EU `api.eu.lever.co`). Its public README (lever/postings-api, read 2026-10-26): "all job postings in the published state are publicly viewable. These jobs may be scraped by third parties." Robots.txt on both API hosts allows every path with `Crawl-delay: 1`, which is honoured. The directory baked into the image was built on 2026-10-26 from company names in the Remote OK feed and five seed boards, each verified against its public board endpoint; the `directory` object on a run's first record gives the build date of the directory that run used. Only process content you have the right to process. Every request obeys HermesBot robots-group selection, the shared deny-list, public-address checks on connections and redirects, an honest user-agent, a 30-second deadline per request and at most one request a second per host (Lever and Remote OK ask `Crawl-delay: 1`). No caller credentials, cookies, CAPTCHA solving, residential proxies or evasion. Job text is returned with email addresses and phone numbers redacted; no recruiter, applicant or hiring-team object is ever read or returned, and the application endpoints are never called.

### Not affiliated

This Actor is not affiliated with Greenhouse Software, Lever, Apify or the companies whose boards it reads. Third-party names describe the sources.

### Related Hermes Actors

- [Greenhouse Job Board Scraper — Open Jobs, Live, Any Company](https://apify.com/hermeskd/greenhouse-jobs) — every open job on a company's Greenhouse board.
- [Lever Jobs Scraper — Postings from Any Lever Site, US & EU](https://apify.com/hermeskd/lever-jobs) — every published job on a company's Lever site, global or EU.
- [Company ATS Finder — Which Hiring System & Job Board It Uses](https://apify.com/hermeskd/company-ats-board) — which hiring system and job board a company uses.
- [Remote Jobs Scraper — Remote OK Listings, Salary Filter, Links](https://apify.com/hermeskd/remote-jobs) — current remote jobs from Remote OK, with salary and listing links.
- [URL to Markdown for LLMs — From $0.001 a Page, Agent-Payable](https://apify.com/hermeskd/url-to-markdown) — a public job page as clean Markdown where the site allows it (deny-listed job sites are refused).
- [Speech to Text — Transcribe & Translate to English, SRT/VTT](https://apify.com/hermeskd/audio-to-transcript) — speech to text with SRT and VTT subtitles.
- [Video Converter & MP4 to MP3 — Trim, GIF; Audio $0.001 a Minute](https://apify.com/hermeskd/audio-video-convert) — audio and video conversion: MP4 to MP3, trim, GIF.
- [Broken Link Checker That Never Charges for the Broken Links](https://apify.com/hermeskd/broken-links) — broken links, 404s and redirects on a site.
- [DNS Lookup & SPF, DKIM, DMARC Check — Findings by Severity](https://apify.com/hermeskd/dns-and-email-auth) — DNS records and SPF, DKIM and DMARC checks.
- [Word, Excel & PowerPoint to Markdown — $0.002 per Document](https://apify.com/hermeskd/document-to-markdown) — Word, Excel, PowerPoint and other office files to Markdown.
- [Domain Availability Checker — Registry RDAP, No Contact Data](https://apify.com/hermeskd/domain-availability) — whether domain names are available, from registry RDAP.
- [Image to Text OCR — Lines & Words with Boxes, $0.002 an Image](https://apify.com/hermeskd/image-to-text) — OCR: the text in images.
- [Image Upscaler — AI Upscale Graphics, Screenshots & Text 2x/4x](https://apify.com/hermeskd/image-upscale) — AI upscaling of graphics, screenshots and text, 2x or 4x.
- [Lighthouse Audit, No API Key — Lab Core Web Vitals & SEO Scores](https://apify.com/hermeskd/lighthouse-audit) — Lighthouse scores and Core Web Vitals.
- [PDF to Markdown & Text — $0.0005 a Text Page, OCR for Scans](https://apify.com/hermeskd/pdf-to-markdown) — PDF to Markdown and text, with OCR for scanned pages.
- [SEO Audit — On-Page Checks, Schema & Hreflang, $0.004 a Page](https://apify.com/hermeskd/seo-page-audit) — an on-page SEO audit: meta tags, schema, headings and links.
- [Sitemap URL Extractor — Indexes, Gzip, RSS; $0.0003 per URL](https://apify.com/hermeskd/sitemap-urls) — the URLs in a site's sitemaps.
- [Video Frame Extractor — by Scene, Interval or Timestamp](https://apify.com/hermeskd/video-frames) — frames, thumbnails and scenes from a video.
- [Website Screenshot API — Elements, HTML, Dark Mode & PDF Print](https://apify.com/hermeskd/website-screenshot) — screenshots and PDF prints of web pages.

### Changelog

2026-10-26: first version (build unit 5): the directory and its postings index, live confirmation, closed-posting drop, the one-time search charge; listing written to the amended store contract.

# Actor input Schema

## `query` (type: `array`):

Keywords; a posting matches when its title or a department contains any of them (case-insensitive words or phrases); 1–50.

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

Return only postings whose location text, city, region or country matches any of these.

## `countries` (type: `array`):

Return only postings whose stated location is in one of these countries (ISO 3166-1 alpha-2 codes).

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

Return only postings the board marks remote.

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

Return only postings in a department (or Lever team) containing any of these words.

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

Search only these companies' boards (company names or board tokens); 1–100.

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

Return only postings first published or created in the last N days; 1–3,650, default 30.

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

Most confirmed matches returned, newest first; 1–1,000.

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

Return each posting's description as redacted Markdown.

## Actor input object example

```json
{
  "query": [
    "engineer"
  ],
  "remoteOnly": false,
  "postedWithinDays": 30,
  "maxResults": 10,
  "includeDescription": false
}
```

# Actor output Schema

## `results` (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 = {
    "query": [
        "engineer"
    ],
    "maxResults": 10
};

// Run the Actor and wait for it to finish
const run = await client.actor("hermeskd/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 = {
    "query": ["engineer"],
    "maxResults": 10,
}

# Run the Actor and wait for it to finish
run = client.actor("hermeskd/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 '{
  "query": [
    "engineer"
  ],
  "maxResults": 10
}' |
apify call hermeskd/ats-job-search --silent --output-dataset

```

## MCP server setup

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