# ATS Jobs Scraper & Change Monitor (`cemented_jest/ats-jobs-change-monitor`) Actor

Collect Greenhouse, Lever and Ashby jobs in one schema. Track changes to job details and compensation with private snapshots and CSV-ready output.

- **URL**: https://apify.com/cemented_jest/ats-jobs-change-monitor.md
- **Developed by:** [CRNO](https://apify.com/cemented_jest) (community)
- **Categories:** Automation
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 delivered records

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 Scraper & Change Monitor

Collect Greenhouse, Lever and Ashby jobs in one schema. Track changes to job details and compensation with private snapshots and CSV-ready output.

### Quick start

Run the example below. No source API key or proxy subscription is required for the supported public endpoints. Source access can still be rate-limited or blocked. Results are stored in the default dataset, ready for JSON, CSV or Excel export.

```json
{
  "boards": [
    "greenhouse:figma"
  ],
  "maxItems": 20
}
```

### What you receive

Every row includes a stable `id`, `source`, `title`, `url`, UTC `observedAt` and `runId`. Source-specific fields include board, location, departments, employmentType, publishedAt, updatedAt, descriptionHtml, compensation. Optional source values may be null or empty. Nested arrays are preserved in JSON.

Input order determines which boards fill the total result limit. Greenhouse and Ashby return full public boards; Lever is paginated. Description HTML is source content and must be sanitized before displaying on a website. No candidate profiles or application submissions are collected. Missing jobs are not labelled closed. Lever and Ashby dates reflect the upstream meaning, not guaranteed original publication dates.

#### Example result

The following validation result shows the output structure. Long text and arrays are shortened for readability; values are historical examples, not current source values.

```json
{
  "id": "5426468004",
  "source": "greenhouse",
  "title": "Account Executive, Enterprise",
  "url": "https://boards.greenhouse.io/figma/jobs/5426468004?gh_jid=5426468004",
  "board": "figma",
  "location": "San Francisco, CA • New York, NY • United States",
  "departments": [
    "Sales"
  ],
  "employmentType": null,
  "publishedAt": null,
  "updatedAt": "2026-10-27T13:40:12-04:00",
  "descriptionHtml": "&lt;div class=&quot;content-intro&quot;&gt;&lt;p&gt;Figma is growing our team of passionate creatives and builders on a mission to make design accessible to all. Figma’s platform helps teams bring ideas to life—whether you&#39;re brainst...",
  "compensation": null,
  "changeType": "baseline",
  "changedFields": [],
  "previousObservedAt": null,
  "observedAt": "2026-11-05T07:33:21.220Z",
  "runId": "QfCRbVo2bVZ1gNVem"
}
```

### Inputs

| Field | Meaning | Default |
| --- | --- | --- |
| `boards` | Use provider:slug. Providers: greenhouse, lever, lever-eu, ashby. Find the slug in the public career-page URL. No login required. | `["greenhouse:figma"]` |
| `keyword` | Case-insensitive filter on title, location and department. | `""` |
| `maxItems` | Maximum matching records to select (1–1000), across all sources in input order. Source APIs may return or scan additional rows before filtering. In changes-only mode this caps compared records, not just delivered changes. | `100` |
| `trackChanges` | Save a private snapshot and compare the same input selection across runs. | `false` |
| `historyStoreName` | Required for change tracking. Choose a private key-value store owned by your account; reuse it on later runs. | `""` |
| `onlyChanges` | Requires change tracking. The first run returns all baseline records; later unchanged records are free and omitted. | `false` |

### Change monitoring

Set `trackChanges: true` and a private `historyStoreName`, then reuse exactly the same search inputs and maximum-results setting on later runs. An Apify schedule can run this daily; scheduling and notifications are configured by you, not automatically created by this Actor. Use `onlyChanges: true` to omit unchanged rows.

The first run emits `baseline` rows. Subsequent rows are `new`, `changed` or `unchanged`, with `changedFields` and `previousObservedAt`. Without tracking, the label is `notTracked`. Comparisons cover only the selected result window and immediately preceding successful snapshot. Newly seen does not mean newly created. Missing records are not declared deleted, closed or resolved. Source-fetch failures and budget-truncated selections do not advance the baseline. A storage failure after delivery can leave saved rows or a saved snapshot; check the dataset and SUMMARY before retrying. Avoid overlapping scheduled runs for the same history; immutable snapshots prevent one run overwriting another. Rotate the history store after 2,000 snapshots per search.

### Pricing

**$2.00 per 1,000 delivered records ($0.002 each).** Only the `record-scraped` event is billed. No startup fee, no separate automatic dataset-item fee. Actor platform usage is included. Empty results and omitted unchanged records have no result fee. Account-level charges for later storage/API usage, schedules or integrations follow your Apify plan.

Set an Apify maximum charge limit to cap result spending. `maxItems` limits inspected records, including unchanged ones. A small charge budget may further limit the selection. The `SUMMARY` record has no result-event fee and reports fetched/saved counts, budget stops, request counts and snapshot status.

### Reliability and limits

At most 1,000 selected records and 60 source requests per run; each request has a 30-second timeout and a 16 MB response limit. Requests are paced, temporary errors receive bounded retries, and source failures or malformed responses fail explicitly. A run collects the selected rows before writing them, so an upstream error does not silently return partial success. Delivery or storage failures can leave output; inspect SUMMARY before retrying. Start a new run instead of resurrecting an existing output dataset.

Public APIs can change, return stale data or limit requests. No scraper can guarantee permanent availability or exhaustive coverage. This is an independent tool, not an official service of the source organization. Users are responsible for their downstream use and applicable source terms; public access is not an unrestricted redistribution license.

### Source documentation

[Official source/API documentation](https://docs.greenhouse.io/job-board.html). For support, open an issue on this Actor with the run ID and non-sensitive input. Never include tokens or confidential data.

# Actor input Schema

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

Use provider:slug. Providers: greenhouse, lever, lever-eu, ashby. Find the slug in the public career-page URL. No login required.

## `keyword` (type: `string`):

Case-insensitive filter on title, location and department.

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

Maximum matching records to select (1–1000), across all sources in input order. Source APIs may return or scan additional rows before filtering. In changes-only mode this caps compared records, not just delivered changes.

## `trackChanges` (type: `boolean`):

Save a private snapshot and compare the same input selection across runs.

## `historyStoreName` (type: `string`):

Required for change tracking. Choose a private key-value store owned by your account; reuse it on later runs.

## `onlyChanges` (type: `boolean`):

Requires change tracking. The first run returns all baseline records; later unchanged records are free and omitted.

## Actor input object example

```json
{
  "boards": [
    "greenhouse:figma"
  ],
  "keyword": "",
  "maxItems": 100,
  "trackChanges": false,
  "historyStoreName": "",
  "onlyChanges": false
}
```

# Actor output Schema

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

No description

## `summary` (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 = {};

// Run the Actor and wait for it to finish
const run = await client.actor("cemented_jest/ats-jobs-change-monitor").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("cemented_jest/ats-jobs-change-monitor").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 cemented_jest/ats-jobs-change-monitor --silent --output-dataset

```

## MCP server setup

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

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/LqyDNRbcGIbx0WgFu/builds/kfaG7TICLbDSYiKnF/openapi.json
