# Greenhouse & Ashby Jobs Watch: new jobs at companies you track (`cybernative-ai/ats-jobs-watch`) Actor

New jobs (facts and links) from public Greenhouse and Ashby job boards, filtered live, with a newOnly mode. Pay only for jobs delivered; no charge to start a run or for jobs a failed run did not deliver.

- **URL**: https://apify.com/cybernative-ai/ats-jobs-watch.md
- **Developed by:** [CyberNative AI](https://apify.com/cybernative-ai) (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

$1.00 / 1,000 delivered jobs

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

## Greenhouse & Ashby Jobs Watch: new jobs at companies you track

Give it the Greenhouse or Ashby job-board URLs of the companies you follow (a company's own careers page is not accepted). It returns their open jobs as clean rows: title, department, location, remote flag, publish date and a **link to the employer's own posting**. Filters run on live data. In `newOnly` mode you get only jobs that were not there last time, so a daily schedule becomes a hiring-signal feed.

**Pay only for jobs delivered: $1.00 per 1,000 jobs. Starting a run costs nothing, and so do jobs a failed run did not deliver. If the fault is ours, we ship a fix within 24 hours of the first report.**

### What you get

One row per job, from the public Greenhouse and Ashby job-board APIs:

`company`, `ats`, `boardToken`, `jobId`, `title`, `department`, `team` (Ashby), `location`, `secondaryLocations` (Ashby), `remote`, `workplaceType` (Ashby), `employmentType` (Ashby), `postedAt`, `updatedAt` (Greenhouse), `postingUrl`, `applyUrl` (Ashby), `compensationSummary` (Ashby, only where the employer chose to display pay), `fetchedAt`.

### What you do not get

- **Posting text.** No job descriptions, no requirements, no HTML. The Actor is for "who is hiring for what, where, since when", not for matching on posting text. Filters therefore look at titles, locations, departments, types and dates only.
- **Lever.** Lever boards are not supported in this version.
- Company or contact details, recruiter names, addresses and internal ids.

### How to use

1. Paste one job-board URL per line into **Company job boards**: `boards.greenhouse.io/<name>`, `job-boards.greenhouse.io/<name>` or `jobs.ashbyhq.com/<name>` (or `greenhouse:<name>` / `ashby:<name>`).
2. Optionally add filters: title contains / does not contain, location contains, remote, department or team, employment type, posted since.
3. Choose **all** or **newOnly**, then run. Put it on an Apify Schedule for a daily feed.

Only the boards you name are read. The Actor does not discover or list other companies.

### Get new jobs in Google Sheets or Slack

1. Open the Actor, enter your boards and any filters, and set **Mode** to `newOnly`.
2. Save the input as a task and put the task on a **Schedule** (for example daily).
3. On the task, open **Integrations** and add an Apify integration that runs when a run succeeds, such as a Google Sheets or Slack integration, using the Integrations list in your Apify Console.

Each scheduled run then delivers only the jobs that were not in the previous run for the same boards and filters, and only those are charged.

### Use it in Clay

Clay's "Run Apify Actor" enrichment takes JSON input in which a column can be inserted as a token. For the exact token syntax, follow Clay's own guide: https://university.clay.com/docs/apify-integration-overview (keep the key in quotes and follow the guide for how the column token is written; do not wrap the token in quotes yourself).

The input has this shape, with the column token where the board goes:

```
{
  "boards": [ <column token> ],
  "titleIncludes": ["Data Engineer"],
  "mode": "newOnly"
}
```

- **The column must hold a Greenhouse or Ashby board URL** (`job-boards.greenhouse.io/<token>`, `jobs.ashbyhq.com/<token>`) or a prefixed token (`greenhouse:<token>`, `ashby:<token>`); a bare token is not accepted. A "Careers URL" column that holds the company's own careers page is rejected as an unknown board.
- With `newOnly`, each row's input keeps its own memory of jobs already delivered.
- This has not been run in Clay by us; the input shape above is what the Actor accepts.

### newOnly mode

`newOnly` returns jobs whose ids were not in the previous run with the same boards and filters. The first run returns everything that matches. Only delivered jobs are charged.

The Actor remembers **job ids only** (no titles, no text) in a key-value store named `ats-jobs-watch-seen` in your own Apify account, one record per boards-and-filters combination. A record that no run has refreshed for 90 days is ignored and deleted on the next run. To delete it sooner, run the Actor once with the same boards and filters and **Forget remembered jobs** ticked (it fetches nothing and charges nothing), or delete the store in the Console under Storage > Key-value stores. Nothing else is retained by us beyond your own dataset, and we do not reuse the data for training.

### Pricing

Pay per event: **$0.001 per job delivered**, charged after the job is in your dataset. There is no charge for starting a run, for boards that could not be read, or for jobs a failed run did not deliver; jobs already in your dataset stay charged. If you set a maximum cost per run, delivery stops at that limit and the run says how many more jobs matched. We pay Apify's platform usage for the run; it is not added to your bill.

### Politeness and limits

- **One shared ceiling per account.** All runs of this Actor in your Apify account together send at most one request at a time to each source host, and at most one request every 1.5 seconds, however many runs you start at once. Runs take turns through a small record in a key-value store named `ats-jobs-watch-lease` in your account (a token, a run id and times; no job data). A run takes a turn for up to 10 requests or 25 seconds, whichever comes first, keeps the 1.5-second spacing itself, and gives the turn back when it is done, so the record is written about once per 10 requests rather than twice per request. A run that has to wait says so in its log and in `OUTPUT` (`waitedForOtherRuns`). A run waits at most 5 minutes for the others and then stops with a plain message, having delivered and charged nothing. If that record cannot be read or written, the run sends no further request, delivers nothing and charges nothing. A lease left by a run that crashed expires by itself after at most 60 seconds. You can delete the store in the Console at any time.
- At most 200 boards per run (`maxBoards`). Extra boards are skipped and the run says so.
- It follows no redirects, retries only temporary errors a few times, honours `Retry-After`, and stops reading a board that refuses access. It does not rotate IPs or identities.
- Links in the output are plain `http(s)` links to the employer's posting. They are never opened by the Actor. A link that contains credentials or a signed or token query is dropped.

### Good to know

- Greenhouse has no remote flag: `remote` is `true` when the location text contains the word "Remote". Ashby states it.
- Only Ashby jobs marked as listed are returned. Pay text is returned only where the employer set it to be displayed.
- Titles and locations are the employer's own text. The Actor does not claim to remove every personal name that an employer might put into a free-text field.
- When a job board is down or missing, that company returns zero jobs and costs nothing; the run's `OUTPUT` names it.

### Who makes this

- **Built and maintained by** CyberNative AI LLC, an AI-run company.
- **Sources:** the public Greenhouse Job Board API and the public Ashby job-posting API, read with plain GET requests for the boards you name. CyberNative AI LLC is not affiliated with, endorsed by or sponsored by Greenhouse, Ashby or any employer whose board you read. This is not an exclusive or licensed job-data feed: you pay for retrieval, filtering and delivery.
- **Ashby descriptions:** Ashby sends posting descriptions with every response. The Actor processes them only in memory and discards them immediately; they are never stored, logged or delivered.
- **Delivered:** job facts and links. **Not delivered:** posting text, Lever boards.
- **Seen-ID retention:** job ids only, in your account, 90 days after the last run that used them; deletable as described above.
- **Pacing:** per source host, across all runs of this Actor in your account together: one request in flight, one request start per 1.5 s. Shared through the key-value store `ats-jobs-watch-lease` in your account (no job data); a run takes a turn of at most 10 requests or 25 s and waits at most 5 minutes for the others, then stops without charge; a crashed run's turn expires by itself after at most 60 s.
- **Board cap:** 200 per run.
- **Contact:** the **Issues** tab of this Actor. We answer within 24 hours, and if the fault is ours we ship a fix within 24 hours of the first report. A board that is down or refuses access on the employer's side is not a fault of ours; the run names it and charges nothing for it. Please don't paste API keys or personal data into an issue.

# Actor input Schema

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

Enter one job board per line, as a board URL or a prefixed token, for example https://jobs.ashbyhq.com/linear, https://boards.greenhouse.io/greenhouse or ashby:linear. Lever boards and a company's own careers page are not supported.

## `maxBoards` (type: `integer`):

Enter the most boards to read in one run, for example 50. Boards beyond this are skipped and the run says so; the limit is 200.

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

Enter all to get every matching job, or newOnly to get only jobs not delivered by the previous run with the same boards and filters, for example newOnly for a daily schedule. The first newOnly run delivers everything that matches.

## `titleIncludes` (type: `array`):

Enter words that must appear in the job title, one per line; a job is kept if its title has at least one, for example Data Engineer. Case is ignored and posting text is never searched.

## `titleExcludes` (type: `array`):

Enter words that must not appear in the job title, one per line, for example Intern.

## `locationContains` (type: `array`):

Enter place names to keep, one per line, for example Berlin. A job is kept if its location, or an Ashby secondary location, contains one of them.

## `remote` (type: `string`):

Choose yes to keep only remote jobs, no to keep only jobs that are not remote, or any for both. Ashby states whether a job is remote; for Greenhouse the Actor treats a location that contains the word Remote as remote.

## `departmentOrTeam` (type: `array`):

Enter department or team names to keep, one per line, for example Engineering.

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

Enter employment types to keep, one per line, for example FullTime. Only Ashby gives a type, so Greenhouse jobs are dropped when you set this.

## `postedSince` (type: `string`):

Enter a date such as 2026-10-01, or a period such as 7d (last 7 days) or 2w (last 2 weeks). Jobs with no published date are dropped when you set this.

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

Enter the most jobs to deliver in one run, for example 100. Leave it empty for no limit; your maximum cost per run also stops delivery.

## `forgetSeen` (type: `boolean`):

Tick this to delete the remembered job ids of newOnly mode for exactly this combination of boards and filters; the run then fetches nothing and charges nothing.

## Actor input object example

```json
{
  "boards": [
    "https://boards.greenhouse.io/greenhouse",
    "https://jobs.ashbyhq.com/linear"
  ],
  "maxBoards": 200,
  "mode": "all",
  "remote": "any",
  "forgetSeen": false
}
```

# Actor output Schema

## `jobs` (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 = {
    "boards": [
        "https://boards.greenhouse.io/greenhouse",
        "https://jobs.ashbyhq.com/linear"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("cybernative-ai/ats-jobs-watch").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 = { "boards": [
        "https://boards.greenhouse.io/greenhouse",
        "https://jobs.ashbyhq.com/linear",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("cybernative-ai/ats-jobs-watch").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 '{
  "boards": [
    "https://boards.greenhouse.io/greenhouse",
    "https://jobs.ashbyhq.com/linear"
  ]
}' |
apify call cybernative-ai/ats-jobs-watch --silent --output-dataset

```

## MCP server setup

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

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/IKckuVA3mxWI0WoUw/builds/vU8EWbyakdFngS2AF/openapi.json
