# Hiring Signals — Sales Leads from Live Job Postings (`ntriqpro/hiring-signals-leads`) Actor

Turn job postings into B2B sales leads. Name the roles your buyers hire for and get every company that opened one in the last N days: new roles, sample titles, seniority mix, remote share, a strong/moderate/weak signal score and an outreach angle. 2,200+ live company boards built in.

- **URL**: https://apify.com/ntriqpro/hiring-signals-leads.md
- **Developed by:** [daehwan kim](https://apify.com/ntriqpro) (community)
- **Categories:** Lead generation, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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?

Actors are web data automations that power AI and operations. They run on the Apify platform to scrape websites, process data, connect APIs, and automate workflows.
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.

- **AI agents and MCP clients** — the [Apify MCP server](https://docs.apify.com/integrations/mcp.md) at `https://mcp.apify.com` (remote, streamable HTTP, OAuth on first use).
- **Agentic workflows and local Actor development** — [Agent Skills](https://apify.com/.well-known/agent-skills/index.json) with the [Apify CLI](https://docs.apify.com/cli/docs.md): `npm install -g apify-cli`, then `apify login`.
- **JavaScript/TypeScript projects** — the official [JS/TS client](https://docs.apify.com/api/client/js/docs.md): `npm install apify-client`.
- **Python projects** — the official [Python client](https://docs.apify.com/api/client/python/docs.md): `pip install apify-client`.
- **Any other language** — 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

## Hiring Signals — Sales Leads from Live Job Postings

**Give it a few job titles and it reads up to 1,000 of 2,200+ live company job boards (300 by default) and returns 1 row per company that started hiring for those roles inside your time window, plus 1 summary row per keyword.** Each company row carries a signal score, sample titles, the seniority mix and an outreach angle.

**A job posting is a funded budget with a date on it.** When a company opens four data-engineering roles in nine days, somebody just approved a data budget — and that company is a far warmer account than one that merely matches your firmographics.

This Actor turns that into a lead list. Give it the job titles your buyers hire for, and it reads hundreds of live company job boards and returns every company that started hiring for those roles inside your window — with a signal score, the sample titles, the seniority mix, and an outreach angle you can paste into a first line.

***

### What you get

Two kinds of result row.

#### `hiring-signal` — one row per company × keyword

> **Mixpanel opened 21 account executive roles in 10 days (17 senior+, 76% remote) — strong buying signal**

| Field | What it is |
|---|---|
| `companyName`, `domain`, `careersUrl` | The account, and where the postings live |
| `keyword`, `roleCategory` | Which of your keywords fired, and the function it belongs to |
| `newRolesInWindow` | Matching roles first published inside your window — the signal itself |
| `matchedRoles` | Every matching role open right now, new or not |
| `oldestNewPostedAt`, `newestNewPostedAt` | When the hiring wave started and how recent it is |
| `sampleTitles`, `sampleApplyUrls` | Three real postings, so the lead is checkable in one click |
| `seniorityMix` | intern / junior / senior / principal / manager / director / executive counts |
| `remoteShare`, `locations` | Where the team is being built |
| `signalStrength` | `strong` · `moderate` · `weak` |
| `signalScore`, `signalReasons` | The score and the plain-English rules that produced it |
| `whyItMatters` | What a hire in this function means for a seller |
| `suggestedOutreach` | An angle for the first line of the email |
| `totalOpenRoles`, `atsLabel`, `sourceUrl` | Company context and provenance |

#### `keyword-summary` — one row per keyword

Is this a market that is hiring at all, and who is loudest?

> **"data engineer": 57 of 299 companies are hiring (7 strong, 111 new roles in 14d) — hot**

Carries `companiesScanned`, `companiesWithSignal`, `signalSharePercent`, `strongSignals`, `totalNewRolesInWindow`, `momentum` (`hot` / `warm` / `cool` / `cold`) and `topCompanies` — the five best accounts with their careers URLs.

Rows carrying a `noticeCode` are status messages, not results.

Invalid input ends the run as SUCCEEDED with a notice row.

***

### Why this beats a job-posting database

Most "hiring intent" products sell you a snapshot of somebody's crawl, capped at a few thousand rows and days old.

- **Read live, at request time.** Every company board is fetched when you press run. Nothing is served from a cached job database, so a role posted this morning is in this afternoon's run.
- **No row ceiling.** There is no 5,000-record cap. On a paid plan you get every signal the run finds.
- **2,200+ company boards built in.** Every one was verified with a real request when the directory was built — no dead slugs padding the count. Leave `companies` empty and the Actor uses it; fill it in to watch your own target accounts instead.
- **One request per company, however many keywords.** Searching ten keywords costs the same requests as searching one.

***

### Input

| Field | Default | What it does |
|---|---|---|
| `jobKeywords` | `["data engineer", "account executive"]` | The roles your buyers hire for. Multi-word keywords match whole words, so `account executive` will not match *Executive Assistant*. Up to 20 per run. |
| `postedWithinDays` | `14` | How fresh a posting has to be to count as a signal. |
| `minNewRoles` | `1` | How many new roles a company needs before it counts as a lead. Raise it to keep only companies building a whole function. |
| `companies` | *(empty)* | Your own account list — slugs or careers-page URLs. Empty means use the built-in directory. |
| `maxCompanies` | `300` | How many directory boards to read, busiest boards first. |
| `locations` | *(empty)* | Keep only roles whose location mentions one of these. |
| `remoteOnly` | `false` | Count only roles the board marks as remote. |

**Roles with no published posting date** count towards `matchedRoles` but never towards `newRolesInWindow` — a signal you cannot date is a signal you cannot act on.

#### Example

```json
{
  "jobKeywords": ["data engineer", "analytics engineer", "head of data"],
  "postedWithinDays": 21,
  "minNewRoles": 2,
  "maxCompanies": 500
}
```

Every company that opened at least two of those roles in the last three weeks, ranked by how loud the signal is.

***

### Pricing

| Event | Price | When |
|---|---|---|
| `run-started` | $0.005 | Once per run, when the boards start being read |
| `hiring-signal` | $0.02 | Each company × keyword lead written to the dataset |
| `keyword-summary` | $0.02 | Each keyword's market summary row |

A typical run of 2 keywords across 300 companies returns around 130 rows.

Notice rows — no keywords supplied, no signal found, free-plan cap, charge-limit reached — are **not** charged.

**Free Apify plans** receive up to 25 rows per run and finish successfully with a note; there is no per-run lead limit on a paid plan.

***

### Where the data comes from

The public, unauthenticated job-board JSON that each applicant tracking system serves to a company's own careers page:

| ATS | Endpoint |
|---|---|
| Greenhouse | `boards-api.greenhouse.io/v1/boards/<slug>/jobs` |
| Lever | `api.lever.co/v0/postings/<slug>` |
| Ashby | `api.ashbyhq.com/posting-api/job-board/<slug>` |
| Workable | `apply.workable.com/api/v1/widget/accounts/<slug>` |

No login, captcha or anti-bot measure is bypassed. Requests identify themselves honestly as `ntriq-hiring-signals/1.0`, run four at a time with a pause between them, and cost each company exactly one request per run.

**Rebuilding the built-in directory:** `scripts/fetch_sources.sh` → `python3 scripts/extract.py` → `python3 scripts/probe.py` → `python3 scripts/enrich.py` → `python3 scripts/fix_names.py` (every candidate is re-verified against its live ATS endpoint; only a real HTTP 200 survives).

***

### Terms, scope and responsibility

**Read this before you run it.**

- This Actor is **unofficial** and is **not affiliated with, endorsed by or sponsored by** Greenhouse, Lever, Ashby, Workable, or any employer whose board it reads.
- It reads **only publicly available job postings** — the same pages any visitor to the company's careers site can see. It collects no candidate data and no data from behind a login.
- **You are responsible for complying with the terms of service** of each applicant tracking system and each employer whose board you read, and with the laws that apply to you.
- **You are the data controller** for everything you collect with it, including any GDPR, CCPA or equivalent obligations that follow from using it for outreach.
- Company names, domains and postings are **facts published by the companies themselves**. Signal scores, `whyItMatters` and `suggestedOutreach` are **our rule-based interpretation**, shown with their reasons on every row so you can judge them — they are commentary, not a claim about anyone's finances or intentions.

Ticking **"I understand how this Actor sources data"** confirms you have read this section.

***

### Next steps

- **[ATS Jobs Scraper](https://apify.com/ntriqpro/ats-jobs-scraper)** — pull every open role at a company that signalled here, with full titles, locations, salary and descriptions from the same live board.
- **[theHarvester OSINT](https://apify.com/ntriqpro/theharvester-osint)** — turn a signalling company's domain into public contact points so the lead becomes an outreach list.

***

Built by [ntriqpro](https://apify.com/ntriqpro). Found it useful, or found a gap? A line in the [reviews](https://apify.com/ntriqpro/hiring-signals-leads/reviews) helps the next person decide.

# Actor input Schema

## `jobKeywords` (type: `array`):

The roles that mean somebody just approved a budget you can sell into. A company that opened three data-engineering reqs this month is buying data tooling this quarter. Multi-word keywords match as a whole — "account executive" will not match "Executive Assistant". Up to 20 keywords per run; each one is charged one summary row. Free plan: each run returns up to 25 results. Paid Apify plans receive the full result set.

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

How fresh a posting has to be to count as a signal. 14 days is the default: long enough to catch a hiring wave, short enough that the budget conversation is still open. Roles whose board publishes no posting date are counted as matching roles but never as new ones — an unprovable signal is worse than none.

## `minNewRoles` (type: `integer`):

How many matching roles a company must have opened inside the window before it counts as a lead. 1 gives you the widest list; raise it to 2 or 3 to keep only companies building out a whole function.

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

Leave empty to scan the built-in directory of 2,200+ verified company job boards. Fill it in to watch your own target accounts instead: company slugs or careers-page URLs, e.g. https://job-boards.greenhouse.io/dropbox, https://jobs.lever.co/binance, https://jobs.ashbyhq.com/linear, https://apply.workable.com/blueground. Greenhouse, Lever, Ashby and Workable are detected automatically.

## `maxCompanies` (type: `integer`):

How many company boards this run reads from the built-in directory, busiest boards first. Higher means more leads and a longer run — every company costs exactly one request no matter how many keywords you searched for.

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

Keep only roles whose location mentions one of these, e.g. London, New York, Germany. Leave empty for every location.

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

Count only roles the board marks as remote. Useful when your product sells to distributed teams.

## `disclaimerAck` (type: `boolean`):

This Actor reads only the public, unauthenticated job-board endpoints that each applicant tracking system serves to a company's own careers page. It is unofficial and not affiliated with Greenhouse, Lever, Ashby, Workable or any employer. You are responsible for complying with each ATS's and each employer's terms of service, and you are the data controller for everything you collect.

## Actor input object example

```json
{
  "jobKeywords": [
    "data engineer",
    "account executive"
  ],
  "postedWithinDays": 14,
  "minNewRoles": 1,
  "companies": [],
  "maxCompanies": 300,
  "locations": [],
  "remoteOnly": false,
  "disclaimerAck": true
}
```

# 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 = {
    "jobKeywords": [
        "data engineer",
        "account executive"
    ],
    "postedWithinDays": 14,
    "minNewRoles": 1,
    "companies": [],
    "maxCompanies": 300,
    "locations": [],
    "remoteOnly": false,
    "disclaimerAck": true
};

// Run the Actor and wait for it to finish
const run = await client.actor("ntriqpro/hiring-signals-leads").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 = {
    "jobKeywords": [
        "data engineer",
        "account executive",
    ],
    "postedWithinDays": 14,
    "minNewRoles": 1,
    "companies": [],
    "maxCompanies": 300,
    "locations": [],
    "remoteOnly": False,
    "disclaimerAck": True,
}

# Run the Actor and wait for it to finish
run = client.actor("ntriqpro/hiring-signals-leads").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 '{
  "jobKeywords": [
    "data engineer",
    "account executive"
  ],
  "postedWithinDays": 14,
  "minNewRoles": 1,
  "companies": [],
  "maxCompanies": 300,
  "locations": [],
  "remoteOnly": false,
  "disclaimerAck": true
}' |
apify call ntriqpro/hiring-signals-leads --silent --output-dataset

```

## MCP server setup

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

```

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/KlRKZEwigZPDCfxeI/builds/Mg6UGQFLEc8ZBMmeD/openapi.json
