# ATS Job Change Monitor — Greenhouse, Lever, Ashby (`marcuslee/ats-career-page-monitor`) Actor

Preview current public Greenhouse, Lever, and Ashby job boards directly, then monitor scheduled Task runs for normalized new, changed, active, and confirmed-removed jobs with full datasets and optional signed webhook alerts.

- **URL**: https://apify.com/marcuslee/ats-career-page-monitor.md
- **Developed by:** [Marcus Lee](https://apify.com/marcuslee) (community)
- **Categories:** Jobs, Automation
- **Stats:** 1 total users, 0 monthly users, 0.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per usage

This Actor is paid per platform usage. The Actor is free to use, and you only pay for the Apify platform usage, which gets cheaper the higher subscription plan you have.

Learn more: https://docs.apify.com/platform/actors/running/actors-in-store#pay-per-usage

## What's an Apify Actor?

Actors are a software tools running on the Apify platform, for all kinds of web data extraction and automation use cases.
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.

In JavaScript/TypeScript projects, use official [JavaScript/TypeScript client](https://docs.apify.com/api/client/js.md):

```bash
npm install apify-client
```

In Python projects, use official [Python client library](https://docs.apify.com/api/client/python.md):

```bash
pip install apify-client
```

In shell scripts, use [Apify CLI](https://docs.apify.com/cli/docs.md):

````bash
# MacOS / Linux
curl -fsSL https://apify.com/install-cli.sh | bash
# Windows
irm https://apify.com/install-cli.ps1 | iex
```bash

In AI frameworks, you might use the [Apify MCP server](https://docs.apify.com/platform/integrations/mcp.md).

If your project is in a different language, use 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

## ATS Job Change Monitor — Greenhouse, Lever, Ashby

### Reliable ATS job changes for downstream data pipelines

Monitor up to 100 direct public Greenhouse, Lever, and Ashby boards from one scheduled Apify Task. Each healthy run returns normalized job data with explicit `new`, `active`, `changed`, and conservatively confirmed `removed` statuses.

- **Stop rebuilding snapshot-diff logic:** receive explicit lifecycle statuses and field-level changes.
- **Reduce false closure signals:** source errors, empty responses, and drops above 50% do not advance removals.
- **Use the data your way:** keep the complete dataset while filtering webhook alerts by keyword, location, or department.
- **Integrate with datasets or webhooks:** optional HMAC-signed webhook delivery includes retry and dead-letter handling; cloud delivery validation is still pending.

**Start with one company:** run a direct current preview first, then create an Apify Task, run a baseline, and schedule delta runs for monitoring.

> **Not affiliated with, endorsed by, or sponsored by Greenhouse, Lever, or Ashby.** Uses their documented public job-posting endpoints only.

> **Does not support:** Workday, LinkedIn, Indeed, Glassdoor, generic career-site discovery, applicant data, browser/proxy bypass, email/Slack/Sheets delivery, or SLA. See [Excluded](#excluded) below.

> **Direct run = safe current preview:** a direct default/delta or explicit `preview` run emits `observation_mode: preview` rows without longitudinal state. It still creates the normal default dataset and `OUTPUT` record under your Apify retention settings. Create a Task for baseline + scheduled delta monitoring; direct `baseline` and `self_test` require a Task.

> **Preview never sends alerts:** filters and alert configuration are ignored in preview, no webhook is validated or delivered, and no Task snapshots, locks, history, caches, request queues, outbox, or DLQ are opened.

#### One-company direct preview

```json
{
  "companies": [
    {"name": "Stripe", "career_page_url": "https://boards.greenhouse.io/stripe"}
  ]
}
````

The schema default is `delta`, but without a Task this is reported as `requested_run_mode: "delta"`, `run_mode: "preview"`, and `mode_coerced: true`. Use `"run_mode": "preview"` to make that choice explicit.

### Use cases

- **Job-data vendors:** maintain an incremental feed without rebuilding snapshot comparison and removal confirmation.
- **Job boards and recruiting products:** synchronize selected companies' openings and identify field-level changes.
- **Talent and market-intelligence teams:** track deterministic job-level changes for downstream analysis without receiving opinionated company-level interpretations.

### Why choose this Actor?

Broad ATS scrapers are better when you need maximum platform coverage or a one-time snapshot. Hiring-signal tools are better when you want ready-made commercial interpretation. Choose this Actor when reliable job-level change detection matters: explicit lifecycle states, conservative removals, source-anomaly protection, complete datasets, and optional filtered alerts.

### Who it is for

This is an integration component for data vendors, job-board operators, and talent-intelligence teams that can consume Apify datasets or webhooks. It is not a consumer job-alert app and does not discover generic career sites.

### Supported behavior

- **New:** first appearance in committed Task state
- **Active:** unchanged since the prior healthy run
- **Changed:** normalized title, location, department, employment type, compensation, job URL, or description hash changed
- **Removed:** absent on two consecutive healthy runs
- Errors, zero-result anomalies, and drops greater than 50% preserve committed state and do not advance removal candidates

### Input

Create an Apify Task with this input. Because the current Apify input schema applies `required` fields unconditionally, `companies` remains required in `self_test` mode even though the self-test uses fixed public probes. The `alerts` object is secret in the Apify input schema, so Apify encrypts its webhook URL and HMAC secret at rest.

| Field | Type | Default | Description |
|---|---|---:|---|
| `companies` | array | required | 1–100 `{name, career_page_url}` records using direct supported ATS board URLs |
| `filters.keywords` | array | `[]` | Alert-only title keywords |
| `filters.locations` | array | `[]` | Alert-only location filters |
| `filters.departments` | array | `[]` | Alert-only department filters |
| `alerts.webhook_url` | string | empty | Public HTTPS webhook destination |
| `alerts.webhook_secret` | string | empty | Optional HMAC-SHA256 secret |
| `run_mode` | enum | `delta` | `delta`, `baseline`, `self_test`, or `preview`; direct default/delta is coerced to preview |
| `first_run_alerts` | boolean | `false` | Alert on jobs committed by a baseline run |
| `timeout_seconds` | integer | `300` | Timeout for each outbound ATS HTTP request |
| `max_companies_per_run` | integer | `100` | Runtime company cap, maximum 100 |

```json
{
  "companies": [
    {"name": "Stripe", "career_page_url": "https://boards.greenhouse.io/stripe"},
    {"name": "Lever Demo", "career_page_url": "https://jobs.lever.co/leverdemo"},
    {"name": "Linear", "career_page_url": "https://jobs.ashbyhq.com/linear"}
  ],
  "run_mode": "delta",
  "first_run_alerts": false
}
```

To enable webhooks, add:

```json
{
  "alerts": {
    "webhook_url": "https://hooks.example.com/ats-monitor",
    "webhook_secret": "replace-with-a-secret"
  }
}
```

### Run modes

- `preview`: current stateless snapshot, with `active` rows, `first_seen_at: null`, no lifecycle deltas, filters, state, Actor event charges, or webhook processing. It works with or without a Task; ordinary Apify compute and storage still incur platform usage costs.
- `baseline`: Task-only; replaces committed jobs for each successfully extracted company, clears inherited removal candidates, and marks current jobs `new`. Alerts are sent only when `first_run_alerts` is true.
- `delta`: Task-only monitoring; compares current extraction with the Task's committed snapshot. A direct default/delta run is a preview instead.
- `self_test`: Task-only; probes the fixed public Greenhouse (`stripe`), Lever (`leverdemo`), and Ashby (`linear`) boards. It writes a run summary but no job rows. Any declared-platform failure fails the Actor run.

### Output

#### Default dataset

Preview, baseline, and delta runs emit one flat row per returned current or confirmed-removed job. Self-test emits no dataset rows.

| Field | Description |
|---|---|
| `monitor_id` | 16-character hash of an identity-safe normalized returned job URL; identity query parameters such as `gh_jid` are retained |
| `company` | Input display name |
| `ats_source` | `greenhouse`, `lever`, or `ashby` |
| `ats_job_id` | ATS-provided job identifier |
| `job_id` | `{normalized-company}-{ats_job_id}` |
| `title`, `location`, `department` | Current ATS fields |
| `employment_type`, `compensation` | Current values when supplied |
| `job_url` | Returned public posting URL |
| `description_hash` | SHA-256 hash; full descriptions are not stored |
| `first_seen_at` | First monitoring observation timestamp, preserved across active/changed runs; `null` in preview |
| `last_seen_at` | Latest healthy observation timestamp |
| `status` | `new`, `active`, `changed`, or confirmed `removed` |
| `change_summary` | Field-level old/new values for changed rows |
| `run_id`, `run_timestamp` | Run correlation fields |
| `observation_mode` | `preview` for a stateless direct snapshot or `monitoring` for Task lifecycle rows |

#### Run summary

A sanitized `OUTPUT` record is written to the run's default key-value store and linked from the Apify Output tab. It contains counts, requested/effective mode, coercion, monitoring/filter flags, timestamp, and sanitized company errors. Preview adds `active_jobs` and guarantees zero `new_jobs`, `changed_jobs`, and `removed_jobs`. Durable snapshots, webhook destinations, pending payloads, and DLQ records are not exposed there.

### Webhooks

> **Webhook delivery, signing, retry, and DLQ behavior is locally tested but has not been cloud-validated.** Cloud acceptance remains pending.

Delivery is **at least once**, not exactly once. Receivers must deduplicate `X-Webhook-Event-Id`.

- Filters apply consistently to new, changed, and removed alert jobs; dataset output remains unfiltered.
- No event is staged when no webhook is configured or all filtered groups are empty.
- Configured destinations must be public HTTPS endpoints. Literal and DNS-resolved loopback, private, link-local, reserved, multicast, unspecified, and cloud-metadata addresses are rejected.
- Delivery pins the validated public IP while retaining the original HTTPS Host/TLS SNI and does not follow redirects.
- Pending events retain their staging destination. A destination mismatch, including a legacy empty destination, is verified into the DLQ before the pending record is tombstoned.
- Failed events retry across runs and move to the DLQ after five total attempts. The DLQ write is read back before the outbox record is removed.
- `X-Webhook-Signature` is HMAC-SHA256 when a secret is configured.

Example payload:

```json
{
  "run_id": "run-f654a7aacd38",
  "run_timestamp": "2026-07-10T08:00:00Z",
  "company": "Stripe",
  "new_jobs": 1,
  "changed_jobs": 0,
  "removed_jobs": 0,
  "jobs": [
    {"status": "new", "title": "Account Executive", "location": "Remote", "department": "Sales", "url": "https://example.com/jobs/123"}
  ]
}
```

### Pricing

This Actor runs under Apify's **pay-per-usage** model with **no Actor event charges** during an initial validation period (suggested 30 days). The code has no `Actor.charge()` calls, so there is no enforcement mechanism for the validation period — it is a manual policy. Ordinary Apify compute and storage still incur platform usage costs, including dataset and KV store reads/writes. Per-row billing is intentionally not used because unchanged `active` rows would bill noise. A separate price decision may follow after measured cloud costs and repeat usage.

### State and concurrency

The Actor's normal execution path derives one named KVS per Task: `ats-monitor-state-{actor_task_id}`. It stores flat `snapshot--…`, `outbox--…`, `dlq--…`, and `history--…` keys and does not enumerate other Task stores. This is namespace separation in the Actor's code path, **not** a claim that the named store is a separate platform ACL or tenant security boundary.

There is no atomic lock. Overlapping baseline/delta runs can corrupt logical state; configure schedules so runs cannot overlap.

### Failure behavior

| Condition | Behavior |
|---|---|
| Board 404, timeout, malformed response, rate limit | Company skipped, prior state preserved, sanitized error recorded |
| Zero jobs or >50% drop | Removal progression suppressed; prior committed state retained |
| Direct default/delta or `preview` | Stateless current preview; no Task state, filters, or webhooks |
| Direct `baseline` or `self_test` | Run fails before extraction or side effects |
| Invalid/private webhook destination | Run fails before state/outbox mutation |
| Webhook failure | Durable retry, then verified DLQ after five attempts |
| Any self-test platform failure | Self-test run fails visibly |

### Platform and compliance boundary

The Actor uses public job-posting endpoints documented by [Greenhouse](https://developers.greenhouse.io/job-board.html), [Lever](https://github.com/lever/postings-api), and [Ashby](https://developers.ashbyhq.com/docs/public-job-posting-api). It uses no login, applicant/account data, private endpoints, browser automation, proxy rotation, or anti-bot bypass. It is not affiliated with, endorsed by, or sponsored by those companies; their names and trademarks belong to their owners.

Users are responsible for lawful use and for compliance with Apify's terms, each source site's terms, robots/content signals, and applicable privacy/data rules. “Public” does not grant unrestricted reuse rights. Do not configure boards you are not authorized to monitor. Some sites' terms may prohibit automated access even to public endpoints; Apify may receive takedown requests and the user bears that risk.

The Actor stores only selected public posting fields plus a description hash; it does not store full descriptions or applicant data. Dataset items follow the retention policy of the user's Apify account. Task-local snapshots/outbox/DLQ have no Actor-enforced TTL and remain until overwritten or the associated store/Task data is deleted. Webhook receivers control their own downstream retention.

<a id="excluded"></a>

### Excluded

Workday, LinkedIn, Indeed, Glassdoor, generic career-site discovery, applicant data, full description storage, browser fallback, email/Slack/Sheets delivery, and any SLA.

### Known limitations

- Maximum 100 companies per run; runtime/cost vary with board size and pagination.
- Public ATS contracts may change; run `self_test` before relying on a new build.
- No automatic retry of rate-limited ATS extraction inside the same run.
- At-least-once webhooks can duplicate deliveries — receivers must deduplicate by `X-Webhook-Event-Id`.
- No overlapping-run protection. Schedule intervals must exceed the Actor's typical runtime.
- Direct-preview private-cloud acceptance passed for one Greenhouse board and two direct runs. Behavior under rate-limiting, large boards (100+ pages), concurrent users, or sustained scheduled operation has not been cloud-tested.
- Webhook delivery, signing, retry, and DLQ are locally tested, not cloud-validated.
- Self-test mode requires `companies` in the input due to Apify schema constraints, but self-test does not scrape them — it uses fixed public probes.

### Development

Cloud acceptance must use a private duplicate Actor so the public Store metadata and README cannot change before the separate publication gate.

```bash
uv venv --python 3.14 .venv
uv pip install --python .venv/bin/python -r requirements-dev.txt
PYTHONPATH=. .venv/bin/pytest
PYTHONPATH=. .venv/bin/pytest tests/test_live_probes.py --run-live
APIFY_CLI_DISABLE_TELEMETRY=1 npx --yes apify-cli@latest validate-schema
docker build -t ats-career-page-monitor .
```

# Actor input Schema

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

Companies and direct public ATS job-board URLs to monitor (maximum 100).

## `filters` (type: `object`):

Optional filters applied to webhook alerts only. Dataset output remains unfiltered.

## `alerts` (type: `object`):

Optional at-least-once webhook delivery. Receivers should deduplicate X-Webhook-Event-Id.

## `run_mode` (type: `string`):

Direct delta/default runs become a stateless preview. Persistent delta monitoring requires a Task. Baseline and self-test require a Task; preview never uses Task state or sends webhooks.

## `first_run_alerts` (type: `boolean`):

When enabled, treat all jobs on the first baseline as alertable new jobs.

## `max_companies_per_run` (type: `integer`):

Hard cap on companies processed in one run.

## `timeout_seconds` (type: `integer`):

Timeout for each outbound ATS HTTP request, in seconds. A paginated company may make more than one request.

## Actor input object example

```json
{
  "run_mode": "delta",
  "first_run_alerts": false,
  "max_companies_per_run": 100,
  "timeout_seconds": 300
}
```

# Actor output Schema

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

No description

## `runSummary` (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("marcuslee/ats-career-page-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("marcuslee/ats-career-page-monitor").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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 marcuslee/ats-career-page-monitor --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=marcuslee/ats-career-page-monitor",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

```json
{
    "openapi": "3.0.1",
    "info": {
        "title": "ATS Job Change Monitor — Greenhouse, Lever, Ashby",
        "description": "Preview current public Greenhouse, Lever, and Ashby job boards directly, then monitor scheduled Task runs for normalized new, changed, active, and confirmed-removed jobs with full datasets and optional signed webhook alerts.",
        "version": "1.0",
        "x-build-id": "oaaqdvyP60OFAqZ7F"
    },
    "servers": [
        {
            "url": "https://api.apify.com/v2"
        }
    ],
    "paths": {
        "/acts/marcuslee~ats-career-page-monitor/run-sync-get-dataset-items": {
            "post": {
                "operationId": "run-sync-get-dataset-items-marcuslee-ats-career-page-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for its completion, and returns Actor's dataset items in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        },
        "/acts/marcuslee~ats-career-page-monitor/runs": {
            "post": {
                "operationId": "runs-sync-marcuslee-ats-career-page-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor and returns information about the initiated run in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK",
                        "content": {
                            "application/json": {
                                "schema": {
                                    "$ref": "#/components/schemas/runsResponseSchema"
                                }
                            }
                        }
                    }
                }
            }
        },
        "/acts/marcuslee~ats-career-page-monitor/run-sync": {
            "post": {
                "operationId": "run-sync-marcuslee-ats-career-page-monitor",
                "x-openai-isConsequential": false,
                "summary": "Executes an Actor, waits for completion, and returns the OUTPUT from Key-value store in response.",
                "tags": [
                    "Run Actor"
                ],
                "requestBody": {
                    "required": true,
                    "content": {
                        "application/json": {
                            "schema": {
                                "$ref": "#/components/schemas/inputSchema"
                            }
                        }
                    }
                },
                "parameters": [
                    {
                        "name": "token",
                        "in": "query",
                        "required": true,
                        "schema": {
                            "type": "string"
                        },
                        "description": "Enter your Apify token here"
                    }
                ],
                "responses": {
                    "200": {
                        "description": "OK"
                    }
                }
            }
        }
    },
    "components": {
        "schemas": {
            "inputSchema": {
                "type": "object",
                "required": [
                    "companies"
                ],
                "properties": {
                    "companies": {
                        "title": "Companies",
                        "minItems": 1,
                        "maxItems": 100,
                        "type": "array",
                        "description": "Companies and direct public ATS job-board URLs to monitor (maximum 100).",
                        "items": {
                            "type": "object",
                            "required": [
                                "name",
                                "career_page_url"
                            ],
                            "properties": {
                                "name": {
                                    "title": "Company name",
                                    "type": "string",
                                    "description": "Display name used in output and alerts.",
                                    "editor": "textfield"
                                },
                                "career_page_url": {
                                    "title": "Public ATS job-board URL",
                                    "type": "string",
                                    "description": "Direct Greenhouse, Lever, or Ashby jobs URL. Generic career pages are not discovered automatically.",
                                    "editor": "textfield"
                                }
                            }
                        }
                    },
                    "filters": {
                        "title": "Alert filters",
                        "type": "object",
                        "description": "Optional filters applied to webhook alerts only. Dataset output remains unfiltered.",
                        "properties": {
                            "keywords": {
                                "title": "Title keywords",
                                "type": "array",
                                "description": "Send alerts only for job titles matching at least one keyword.",
                                "editor": "stringList",
                                "items": {
                                    "type": "string"
                                },
                                "default": []
                            },
                            "locations": {
                                "title": "Locations",
                                "type": "array",
                                "description": "Send alerts only for matching locations.",
                                "editor": "stringList",
                                "items": {
                                    "type": "string"
                                },
                                "default": []
                            },
                            "departments": {
                                "title": "Departments",
                                "type": "array",
                                "description": "Send alerts only for matching departments.",
                                "editor": "stringList",
                                "items": {
                                    "type": "string"
                                },
                                "default": []
                            }
                        }
                    },
                    "alerts": {
                        "title": "Webhook alerts",
                        "type": "object",
                        "description": "Optional at-least-once webhook delivery. Receivers should deduplicate X-Webhook-Event-Id.",
                        "properties": {
                            "webhook_url": {
                                "title": "Webhook URL",
                                "type": "string",
                                "description": "Public HTTPS endpoint that receives change alerts. Private, local, reserved, metadata, and unresolved destinations are rejected. Leave empty to disable webhooks.",
                                "editor": "textfield"
                            },
                            "webhook_secret": {
                                "title": "Webhook HMAC secret",
                                "type": "string",
                                "description": "Optional secret used to sign X-Webhook-Signature with HMAC-SHA256.",
                                "editor": "textfield"
                            }
                        }
                    },
                    "run_mode": {
                        "title": "Run mode",
                        "enum": [
                            "delta",
                            "baseline",
                            "self_test",
                            "preview"
                        ],
                        "type": "string",
                        "description": "Direct delta/default runs become a stateless preview. Persistent delta monitoring requires a Task. Baseline and self-test require a Task; preview never uses Task state or sends webhooks.",
                        "default": "delta"
                    },
                    "first_run_alerts": {
                        "title": "Alert on first baseline",
                        "type": "boolean",
                        "description": "When enabled, treat all jobs on the first baseline as alertable new jobs.",
                        "default": false
                    },
                    "max_companies_per_run": {
                        "title": "Maximum companies per run",
                        "minimum": 1,
                        "maximum": 100,
                        "type": "integer",
                        "description": "Hard cap on companies processed in one run.",
                        "default": 100
                    },
                    "timeout_seconds": {
                        "title": "Request timeout",
                        "minimum": 30,
                        "maximum": 600,
                        "type": "integer",
                        "description": "Timeout for each outbound ATS HTTP request, in seconds. A paginated company may make more than one request.",
                        "default": 300
                    }
                }
            },
            "runsResponseSchema": {
                "type": "object",
                "properties": {
                    "data": {
                        "type": "object",
                        "properties": {
                            "id": {
                                "type": "string"
                            },
                            "actId": {
                                "type": "string"
                            },
                            "userId": {
                                "type": "string"
                            },
                            "startedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "finishedAt": {
                                "type": "string",
                                "format": "date-time",
                                "example": "2025-01-08T00:00:00.000Z"
                            },
                            "status": {
                                "type": "string",
                                "example": "READY"
                            },
                            "meta": {
                                "type": "object",
                                "properties": {
                                    "origin": {
                                        "type": "string",
                                        "example": "API"
                                    },
                                    "userAgent": {
                                        "type": "string"
                                    }
                                }
                            },
                            "stats": {
                                "type": "object",
                                "properties": {
                                    "inputBodyLen": {
                                        "type": "integer",
                                        "example": 2000
                                    },
                                    "rebootCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "restartCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "resurrectCount": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "computeUnits": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "options": {
                                "type": "object",
                                "properties": {
                                    "build": {
                                        "type": "string",
                                        "example": "latest"
                                    },
                                    "timeoutSecs": {
                                        "type": "integer",
                                        "example": 300
                                    },
                                    "memoryMbytes": {
                                        "type": "integer",
                                        "example": 1024
                                    },
                                    "diskMbytes": {
                                        "type": "integer",
                                        "example": 2048
                                    }
                                }
                            },
                            "buildId": {
                                "type": "string"
                            },
                            "defaultKeyValueStoreId": {
                                "type": "string"
                            },
                            "defaultDatasetId": {
                                "type": "string"
                            },
                            "defaultRequestQueueId": {
                                "type": "string"
                            },
                            "buildNumber": {
                                "type": "string",
                                "example": "1.0.0"
                            },
                            "containerUrl": {
                                "type": "string"
                            },
                            "usage": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "integer",
                                        "example": 1
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            },
                            "usageTotalUsd": {
                                "type": "number",
                                "example": 0.00005
                            },
                            "usageUsd": {
                                "type": "object",
                                "properties": {
                                    "ACTOR_COMPUTE_UNITS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATASET_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "KEY_VALUE_STORE_WRITES": {
                                        "type": "number",
                                        "example": 0.00005
                                    },
                                    "KEY_VALUE_STORE_LISTS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_READS": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "REQUEST_QUEUE_WRITES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_INTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "DATA_TRANSFER_EXTERNAL_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_RESIDENTIAL_TRANSFER_GBYTES": {
                                        "type": "integer",
                                        "example": 0
                                    },
                                    "PROXY_SERPS": {
                                        "type": "integer",
                                        "example": 0
                                    }
                                }
                            }
                        }
                    }
                }
            }
        }
    }
}
```
