# Company Hiring Signals — Hiring Intent Data for B2B Lead Gen (`arcaedion/company-hiring-signals`) Actor

Which companies are hiring, for what, and how fast? One record per company: open roles, 30-day hiring velocity, engineering/sales/marketing demand, remote share, salary range, tech-keyword counts and change tracking. Input a domain, careers URL or name; 8 ATSes.

- **URL**: https://apify.com/arcaedion/company-hiring-signals.md
- **Developed by:** [Mathews Motta](https://apify.com/arcaedion) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $20.00 / 1,000 company analyzeds

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

## Company Hiring Signals: Hiring Intent Data for B2B Lead Generation

Hiring is one of the strongest public buying-intent signals a company gives away. A company that posts five Salesforce admin roles is buying CRM tooling, a company hiring SDRs is scaling outbound, and an engineering hiring spike often follows funding or a new product push. Company Hiring Signals reads the public job boards of the companies you give it and returns one record per company.

### What does it do

Give the actor companies as domains, careers URLs or names. It finds each company's job board, reads every open role and writes one flat record per company, using public job-board data only.

- **Posting velocity**: open roles, roles posted in the last 7 and 30 days, role age, and a `hiringVelocity` label (hot, growing, steady or low).
- **Function mix**: open roles by function (engineering, data, sales, marketing and more), plus departments, locations and seniority.
- **Focus keywords**: count the open roles that mention your tools or skills, such as `salesforce`, `kubernetes` or `SOC 2`.
- **Change tracking**: with Track changes on, each run reports new and closed roles since the last run.
- **Eight ATS platforms** (Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee and Personio) with one output schema.

### Use cases

**Enrich a lead list.** Export accounts from HubSpot, Salesforce or Clay with a domain column, run the actor on those domains and join the results back on `domain`. Sort by `salesJobs` or `focusKeywordCounts` to see who is investing where you sell.

**Monitor key accounts weekly.** Turn on Track changes, set a monitor name such as `tier-1-accounts` and schedule the actor in Apify Schedules. A webhook into Zapier, Make or n8n can post to Slack when `newJobsSinceLastRun` crosses your threshold.

**Find technographic intent.** Add tools such as `snowflake` or `salesforce` as focus keywords. A company with several open roles mentioning Snowflake is building a data stack, and `jobTitles` lists the matching roles for a specific opener.

### Pricing

- **$0.02 per company analyzed**, when a job board is found and its roles are read.
- **$0.002 per company where no job board was found.**
- **Errors and duplicate entries are free.**
- Apify charges a small actor-start fee per run.

Set a max cost per run and the actor stops once the limit is reached. A list of 1,000 companies where every board is found comes to $20 plus the start fee.

### Input

| Field | Type | Description |
|---|---|---|
| `companies` | string\[] | Required. Domains (`stripe.com`), careers or ATS URLs, or company names. Up to 1,000 per run. |
| `focusKeywords` | string\[] | Optional. Up to 25 whole-word, case-insensitive terms. |
| `includeJobTitles` | boolean | Add up to 50 open roles per company. Default `true`. |
| `trackChanges` | boolean | Compare with the previous run of the same monitor. Default `false`. |
| `monitorName` | string | Snapshot store name for Track changes. Use one per company list. Default `default`. |

Example input:

```json
{
    "companies": [
        "stripe.com",
        "https://jobs.ashbyhq.com/notion",
        "https://jobs.lever.co/spotify"
    ],
    "focusKeywords": ["salesforce", "snowflake", "SDR"],
    "trackChanges": true,
    "monitorName": "tier-1-accounts"
}
```

### Output

One dataset item per company:

| Group | Fields |
|---|---|
| Identity | `input`, `companyName`, `domain`, `ats`, `atsSlug`, `careersUrl`, `status` (`ok`, `not_found` or `error`), `error` |
| Volume | `openJobs`, `jobsAnalyzed`, `truncated`, `remoteJobs`, `remoteShare` (0 to 1) |
| Posting velocity | `jobsPostedLast7Days`, `jobsPostedLast30Days`, `jobsWithPostedDate`, `oldestOpenJobDays`, `medianJobAgeDays`, `hiringVelocity` |
| Function mix | `functionCounts`, `engineeringJobs`, `dataJobs`, `productJobs`, `designJobs`, `salesJobs`, `marketingJobs`, `customerSuccessJobs` |
| Departments and locations | `topDepartments`, `departmentCounts`, `topLocations`, `seniorityCounts` |
| Pay | `jobsWithSalary`, `salaryRange` (annualized min and max) |
| Focus keywords | `focusKeywordCounts`, `focusKeywordsMatchedOn` |
| Roles | `jobTitles`: up to 50 roles with `title`, `url`, `department`, `location`, `postedAt`, `matchedKeywords` |
| Change tracking | `newJobsSinceLastRun`, `closedJobsSinceLastRun`, `openJobsChange`, `previousRunAt` (`null` on the first run) |
| Timestamp | `analyzedAt` |

Sample record from a live run against Notion's Ashby board, with `jobTitles` trimmed to three entries:

```json
{
  "input": "https://jobs.ashbyhq.com/notion",
  "companyName": "Notion",
  "domain": null,
  "ats": "ashby",
  "atsSlug": "notion",
  "careersUrl": "https://jobs.ashbyhq.com/notion",
  "status": "ok",
  "error": null,
  "openJobs": 139,
  "remoteJobs": 0,
  "remoteShare": 0,
  "jobsPostedLast7Days": 13,
  "jobsPostedLast30Days": 40,
  "jobsWithPostedDate": 139,
  "oldestOpenJobDays": 454,
  "medianJobAgeDays": 63,
  "topDepartments": [
    {
      "name": "Sales",
      "count": 48
    },
    {
      "name": "People",
      "count": 17
    },
    {
      "name": "Outcomes Architect",
      "count": 15
    },
    {
      "name": "Engineering",
      "count": 14
    },
    {
      "name": "Marketing",
      "count": 11
    }
  ],
  "departmentCounts": {
    "Sales": 48,
    "People": 17,
    "Outcomes Architect": 15,
    "Engineering": 14,
    "Marketing": 11,
    "Early Career": 8,
    "Finance": 8,
    "Security": 5,
    "Customer Experience": 3,
    "Revenue Operations & Strategy": 3,
    "Product Management": 2,
    "Business Technology": 1,
    "Data Science": 1,
    "Legal": 1,
    "Product Design": 1,
    "User Research and Product Operations": 1
  },
  "topLocations": [
    {
      "name": "San Francisco, California",
      "count": 70
    },
    {
      "name": "New York, New York",
      "count": 49
    },
    {
      "name": "Dublin, Ireland",
      "count": 20
    },
    {
      "name": "Tokyo, Japan",
      "count": 19
    },
    {
      "name": "Paris, France",
      "count": 7
    }
  ],
  "seniorityCounts": {
    "unspecified": 74,
    "manager": 30,
    "lead": 23,
    "executive": 7,
    "intern": 3,
    "senior": 2
  },
  "functionCounts": {
    "engineering": 36,
    "data": 1,
    "product": 2,
    "design": 1,
    "sales": 43,
    "marketing": 13,
    "customer_success": 13,
    "operations": 5,
    "finance": 7,
    "hr_recruiting": 16,
    "legal": 2,
    "other": 0
  },
  "engineeringJobs": 36,
  "dataJobs": 1,
  "productJobs": 2,
  "designJobs": 1,
  "salesJobs": 43,
  "marketingJobs": 13,
  "customerSuccessJobs": 13,
  "jobsWithSalary": 0,
  "salaryRange": null,
  "focusKeywordCounts": {
    "salesforce": 16,
    "kubernetes": 3,
    "SDR": 0
  },
  "focusKeywordsMatchedOn": "title_and_description",
  "hiringVelocity": "growing",
  "jobTitles": [
    {
      "title": "Ecosystem Growth Engineer",
      "url": "https://jobs.ashbyhq.com/notion/45f60d0e-e44f-40c5-985e-4096a8966860",
      "department": "Marketing",
      "location": "New York, New York",
      "postedAt": "2026-10-21T18:45:02.761Z",
      "matchedKeywords": [
        "salesforce"
      ]
    },
    {
      "title": "Sales Strategy & Operations Manager, APAC",
      "url": "https://jobs.ashbyhq.com/notion/b393c25a-2ce7-458d-800a-bf9e75ed070b",
      "department": "Revenue Operations & Strategy",
      "location": "Tokyo, Japan",
      "postedAt": "2026-10-19T02:21:21.108Z",
      "matchedKeywords": [
        "salesforce"
      ]
    },
    {
      "title": "Lifecycle Marketing Manager, Campaign Strategy & Execution",
      "url": "https://jobs.ashbyhq.com/notion/576401b9-66e7-4407-a9e2-8aafaa590082",
      "department": "Marketing",
      "location": "San Francisco, California",
      "postedAt": "2026-10-14T15:38:27.470Z",
      "matchedKeywords": [
        "salesforce"
      ]
    }
  ],
  "jobsAnalyzed": 139,
  "truncated": false,
  "analyzedAt": "2026-10-23T00:35:56.982Z"
}
```

### How hiringVelocity is computed

Let `n` be the roles first posted in the last 30 days and `ratio` be `n` divided by open roles.

- **hot**: `n` is at least 15 and the ratio is at least 30%.
- **growing**: `n` is at least 5 and the ratio is at least 15%.
- **steady**: at least one new role in 30 days.
- **low**: no new roles in 30 days, or no open roles.

The label is `null` when fewer than half the roles carry a posting date. In the sample, 40 of 139 roles were posted in the last 30 days (about 29%), so Notion is `growing` rather than `hot`.

### Supported platforms and detection

Detection runs in this order:

1. **ATS or board URL**: read directly.
2. **Domain**: scan the company website for embedded ATS links, then up to three careers-looking pages.
3. **Fallback**: guess board slugs such as `stripe` from the name or domain on the seven ATSes that can be guessed, and keep the first with open roles.

Workday cannot be guessed, because each board needs a tenant, a `wdN` host and a site name. Paste the careers URL instead, for example `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`.

### Limitations

- **Job function is a keyword heuristic** based on title and department. Expect a few edge cases.
- **Pages that load jobs only in the browser may hide the board.** If the board link is not in the page HTML, paste the board URL.
- **Keyword and date coverage vary by ATS.** SmartRecruiters and Workday match keywords on titles only, and Workday dates are approximate.
- **Boards over 2,000 roles are analyzed on the first 2,000.** `openJobs` still holds the true total.
- **No LinkedIn, Indeed or Glassdoor data.** The actor reads only company ATS boards.

### Integrations

- **API**: start runs and read results through the Apify API, for example with `run-sync-get-dataset-items`.
- **Webhooks**: trigger a workflow when a run succeeds.
- **Zapier, Make, n8n**: send hiring alerts to Slack, email or your CRM.
- **Google Sheets, Clay and exports**: push runs to a sheet with the Apify integrations, call the API from Clay over HTTP, or download JSON, CSV or Excel.

### FAQ

**Is it legal to collect this data?**
The actor reads only public job postings through the public endpoints each ATS provides for its career pages. It does not log in or collect candidate data. You remain responsible for how you use the data, so check the rules that apply to you.

**How accurate is it?**
Role counts, posting dates and locations come straight from the company's job board. Function, seniority and keyword counts are rule-based, so treat them as strong signals rather than audited figures.

**What does `not_found` mean?**
No supported job board was found for the input, or the board exists but lists zero open roles. The run continues, the reason is in `error`, and the row is billed at the lower rate. If a company is missing, paste its careers URL.

**How often should I run it?**
Weekly suits account monitoring and most prospecting lists.

**How fresh is the data?**
Each run reads the live board, so data is as fresh as your last run.

### Related actors

- **[Multi-ATS Jobs Scraper](https://apify.com/arcaedion/ats-jobs-scraper)**: every open job from eight ATS platforms, one record per posting.
- **[Workday Jobs Scraper](https://apify.com/arcaedion/workday-jobs-scraper)**: job postings from any myworkdayjobs.com career site.

# Actor input Schema

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

One entry per company. Each entry can be: <br>• a <b>website domain</b> such as <code>stripe.com</code> - the careers page is scanned for the job board it uses (the best way to feed a CRM / lead list);<br>• a <b>careers page or ATS board URL</b> - fastest and most reliable, e.g. <code>https://boards.greenhouse.io/stripe</code>, <code>https://jobs.lever.co/spotify</code>, <code>https://jobs.ashbyhq.com/notion</code>, <code>https://apply.workable.com/huggingface</code>, <code>https://bunq.recruitee.com</code>, <code>https://knime.jobs.personio.de</code>, <code>https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite</code>;<br>• a <b>company name</b> such as <code>Stripe</code> - common board names are probed automatically (may miss or mismatch for ambiguous names; a domain or URL is safer).<br><b>Billing:</b> companies where a job board is found and analyzed are billed at the full <i>company</i> event. Companies that cannot be resolved are still returned with <code>status: not_found</code> but billed at a much cheaper <i>company-not-found</i> event (probing costs compute). Errors and duplicates are never billed. Up to 1,000 companies per run.

## `focusKeywords` (type: `array`):

Optional. For each keyword you get <code>focusKeywordCounts</code>: the number of open roles mentioning it (case-insensitive, whole-word). A direct <b>buying-intent</b> signal - e.g. <code>salesforce</code> shows who is hiring Salesforce admins, <code>kubernetes</code> or <code>snowflake</code> shows tech stacks, <code>SDR</code> shows outbound sales build-outs, <code>SOC 2</code> shows compliance projects. Matched against the job <b>title and description</b>. Exception: SmartRecruiters and Workday need one extra request per job to read descriptions, so for those two the match uses the <b>title only</b> (see <code>focusKeywordsMatchedOn</code> in every record). Up to 25 keywords.

## `includeJobTitles` (type: `boolean`):

Add <code>jobTitles</code> to every record: up to 50 open roles with title, public posting URL, department, location and posted date - newest first, and roles that match your focus keywords first. Turn off for a leaner dataset / CSV.

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

Compare each company with the previous run of the same <b>Monitor name</b> and add <code>newJobsSinceLastRun</code>, <code>closedJobsSinceLastRun</code>, <code>openJobsChange</code> and <code>previousRunAt</code>. Schedule the Actor weekly to see who is ramping up hiring right now. <b>The first run of a monitor only records the baseline</b> (the delta fields are <code>null</code>). For very large boards that exceed the 2,000-job analysis cap only <code>openJobsChange</code> is available.

## `monitorName` (type: `string`):

Identifies the saved snapshots used by <b>Track changes</b>. Use a different name for each company list (e.g. <code>fintech-prospects</code>) so lists are tracked independently. Snapshots live in a named key-value store (<code>hiring-signals-monitor</code>) in your account.

## Actor input object example

```json
{
  "companies": [
    "stripe.com",
    "https://boards.greenhouse.io/stripe",
    "Notion"
  ],
  "focusKeywords": [
    "salesforce",
    "kubernetes",
    "SDR",
    "snowflake"
  ],
  "includeJobTitles": true,
  "trackChanges": false,
  "monitorName": "default"
}
```

# Actor output Schema

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

One hiring-signals record per input company.

## `summary` (type: `string`):

Per-company status, counts, failures and charged items for this run.

# 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 = {
    "companies": [
        "https://boards.greenhouse.io/stripe",
        "https://jobs.ashbyhq.com/notion",
        "https://jobs.lever.co/spotify"
    ],
    "focusKeywords": [
        "salesforce",
        "kubernetes",
        "SDR"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("arcaedion/company-hiring-signals").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 = {
    "companies": [
        "https://boards.greenhouse.io/stripe",
        "https://jobs.ashbyhq.com/notion",
        "https://jobs.lever.co/spotify",
    ],
    "focusKeywords": [
        "salesforce",
        "kubernetes",
        "SDR",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("arcaedion/company-hiring-signals").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 '{
  "companies": [
    "https://boards.greenhouse.io/stripe",
    "https://jobs.ashbyhq.com/notion",
    "https://jobs.lever.co/spotify"
  ],
  "focusKeywords": [
    "salesforce",
    "kubernetes",
    "SDR"
  ]
}' |
apify call arcaedion/company-hiring-signals --silent --output-dataset

```

## MCP server setup

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

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/p5W9txvcIjLBNb8JQ/builds/cA9VacwKhF0ZZi4gd/openapi.json
