# New Job Postings Monitor: Greenhouse, Lever & Ashby (`lineagersiui/hiring-signal-feed`) Actor

Watch up to 200 companies' Greenhouse, Lever and Ashby job boards and get only NEW job postings since your last run, as compact CRM/webhook rows. $0.002 per new job ($2 per 1,000), nothing else; first run returns the last 7 days. No descriptions or personal data. Free demo.

- **URL**: https://apify.com/lineagersiui/hiring-signal-feed.md
- **Developed by:** [Lineage RSIUI](https://apify.com/lineagersiui) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.00 / 1,000 new job returneds

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

## New Job Postings Monitor: Greenhouse, Lever & Ashby

**Get only the job postings you haven't seen yet, from the companies you care about.** List up to 200 companies' Greenhouse, Lever or Ashby job boards. Each run returns only the postings that this watchlist hasn't returned before, as compact rows that are easy to send to a CRM, Google Sheet, Slack or webhook.

**Who it's for:**

- **Sales and account-based marketing:** a company opening sales or engineering roles is a buying signal. Get it as soon as your next scheduled run.
- **Recruiters and agencies:** see new openings at your target clients first.
- **Market and competitor intelligence:** track who is hiring for what, where, and at what posted salary.

### Try it free first

Run it with empty input. It runs a **free demo**: it reads three public boards and shows up to 10 recent postings. The demo isn't billed and remembers nothing.

### How it works

1. **Add companies**, one per line:
   - as `ats:board`: `greenhouse:stripe`, `lever:spotify`, `lever-eu:yourco`, `ashby:ramp`;
   - or paste the board link: `boards.greenhouse.io/stripe`, `jobs.lever.co/spotify`, `jobs.ashbyhq.com/ramp`;
   - or a bare name (`stripe`), which is looked up on Greenhouse, then Lever, then Ashby.
2. **First run:** postings published in the last **7 days** are returned (you can choose 0-30 days). Older open postings are only remembered, not returned or charged.
3. **Every later run:** only postings that weren't open before. Schedule it hourly or daily. A run with nothing new returns nothing and costs nothing in events.
4. **Optional filters:**
   - title keywords (e.g. `account executive`, `sdr`);
   - title words to exclude (e.g. `intern`);
   - location keywords (e.g. `remote`, `London`).
5. **Separate feeds:** give each a different **watchlist name** (e.g. one per client). Each name keeps its own memory.

### Output

One row per new posting:

| Field | Example |
|---|---|
| `company`, `board`, `ats` | `Acme Inc`, `acme`, `greenhouse` |
| `title`, `department`, `team` | `Account Executive, Mid-Market`, `Sales`, `EMEA` |
| `location`, `country`, `workplaceType`, `employmentType` | `London \| Remote (EU)`, `GB`, `hybrid`, `FullTime` |
| `salary` | `$120K - $160K`: from Lever and Ashby boards, only when the employer published it. Always empty for Greenhouse (its public API has no salary field) |
| `url` | Link to the official posting |
| `publishedAt`, `firstSeenAt` | When the employer published it; when this feed first saw it |
| `jobId`, `watchlist` | Stable id for de-duplication in your own systems |

A `SUMMARY` record (Storage, key-value store) holds:

- **`newJobsByCompany`**, the hiring signal: how many new postings each company opened since the last run;
- the status of every board (`ok`, `not_found`, ...);
- the billing totals.

**Kept compact on purpose:**

- **Not output:** job descriptions, which belong to the employer (open the `url` to read them).
- **No personal data:** custom fields and recruiter details are never output. E-mail addresses and phone numbers are removed from every field.

### Pricing

- **Price: $0.002 per new job ($2 per 1,000).** Each new posting returned is one `new-job` event (pay per event; also shown on the Pricing tab).
- **Not billed:**
  - the demo;
  - runs with nothing new;
  - postings that were already open when you started watching (beyond the lookback);
  - companies checked.
- **Hit your spending limit or maximum?** The rest aren't charged and come on the next run. Within a watchlist, a job is charged at most once; in rare failures a job may be skipped rather than charged.
- **One run per watchlist at a time:** if a run starts while another run is still processing the same watchlist, it stops at once with a message, and nothing is fetched or charged. A run stops paid work about a minute before its time limit, and the remaining new jobs come on the next run. If a run is stopped by its time limit, some new jobs may be skipped (not charged).

### Polite by design

- **Official APIs only:** it reads only the public job-board APIs that Greenhouse, Lever and Ashby publish for job listings, with read-only requests and no login.
- **Pacing:** one request at a time per provider, at least 1 second apart.
- **Backing off:** it stops calling a provider if it is asked to slow down (HTTP 429).
- **Identification:** the user agent is `HiringSignalFeed/1.0`, with a link to this page.
- **Employers:** to have your board left out, open an issue on the **Issues** tab.

### Limits

- **Per run:** 200 boards and up to 5,000 new postings.
- **Unknown names:** a board that doesn't exist is reported as `not_found` in SUMMARY.
- **Lever EU:** boards on Lever's EU instance need the `lever-eu:` prefix.
- **Data:** results reflect what each board published at run time; no completeness guarantee.
- **Memory:** a posting that closes and reopens within 60 days isn't returned again.

### About

- **Independent:** made by an independent developer. Unofficial; not affiliated with or endorsed by Apify, Greenhouse, Lever or Ashby.
- **Built with AI:** built and maintained with the help of AI tools, under the developer's direction.

# Actor input Schema

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

Up to 200. Use ats:board, e.g. greenhouse:stripe, lever:spotify, lever-eu:yourco, ashby:ramp. A board URL also works (boards.greenhouse.io/stripe, jobs.lever.co/spotify, jobs.ashbyhq.com/ramp). A bare name (stripe) is looked up on Greenhouse, then Lever, then Ashby.

## `watchlistName` (type: `string`):

The 'already returned' memory is kept per watchlist name. Use different names for separate feeds (e.g. one per client). A new name starts fresh.

## `firstRunLookbackDays` (type: `integer`):

The first time a board is watched, jobs published in the last N days are returned (and billed) as new; older open jobs are only remembered. 0 = first run returns nothing and just remembers what's open.

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

Case-insensitive. Example: sales, account executive, engineer. Empty = all jobs. Jobs that don't match are remembered and not returned later.

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

Case-insensitive. Example: intern, contract.

## `locationKeywords` (type: `array`):

Matched against location, country and workplace type. Example: remote, London, US.

## `maxNewJobs` (type: `integer`):

Each new job returned is one billed event. New jobs over this limit aren't charged and are returned on the next run.

## `greenhouseDepartments` (type: `boolean`):

Makes one extra request per Greenhouse board to fill the department field.

## Actor input object example

```json
{
  "watchlistName": "default",
  "firstRunLookbackDays": 7,
  "maxNewJobs": 500,
  "greenhouseDepartments": true
}
```

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

// Run the Actor and wait for it to finish
const run = await client.actor("lineagersiui/hiring-signal-feed").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("lineagersiui/hiring-signal-feed").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 lineagersiui/hiring-signal-feed --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,lineagersiui/hiring-signal-feed"
        }
    }
}
```

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/JjlDpUgxO5y7aln2q/builds/nz0uhrKXoYq5bpyV2/openapi.json
