# Hiring Signals – Jobs & Company Intelligence (8 ATS) (`kunnu_data/hiring-signals`) Actor

Give company names, domains or careers pages. Get every open job plus a company-level hiring signal row: hiring velocity, departments, tech stack, salary ranges, remote share. Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio, Teamtailor.

- **URL**: https://apify.com/kunnu_data/hiring-signals.md
- **Developed by:** [Kunal Data](https://apify.com/kunnu_data) (community)
- **Categories:** Lead generation, Jobs, AI
- **Stats:** 2 total users, 1 monthly users, 100.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/actors/running/actors-in-store.md#pay-per-usage

## 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

## Hiring Signals – Jobs & Company Intelligence (8 ATS)

Paste a list of companies — names, domains or careers pages — and get **every open job** plus **one hiring-signal row per company**: how fast they are hiring, which teams are growing, their tech stack, salary ranges, remote share and leadership hires. The actor finds each company's job board automatically across **Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio and Teamtailor**.

### Why use this actor

- **Just company names work.** "Notion", "linear.app" or "https://careers.bunq.com" — the actor detects which ATS the company uses (8 platforms, including white-labelled career domains).
- **Hiring signals, not just job dumps.** Each company row has jobs posted in the last 7/30/90 days, hiring trend, function and seniority mix, GTM expansion, leadership roles and a plain-English `signals` summary.
- **Technographics from job posts.** 180+ technologies and business tools detected (Python, Kubernetes, Snowflake, Salesforce, HubSpot, Gong…) per job and per company.
- **Salaries** from structured pay-transparency fields and from job text (USD, EUR, GBP, INR LPA and more), normalised to min / max / currency / period.
- **Change tracking** for scheduled runs: new and closed roles since the last run.
- **Fast and cheap to run.** Official public job-board feeds, no browser, no proxies. A typical company takes 1–3 seconds.

### Use cases

- **Sales prospecting / ABM** — find accounts that are hiring for the team you sell to (e.g. companies hiring 5+ data engineers who use Snowflake) and time your outreach.
- **Clay / HubSpot / Salesforce enrichment** — add hiring velocity, tech stack and open-role counts to your account list.
- **Recruiting agencies** — spot companies opening many roles in your niche before they hire an agency.
- **Investors and analysts** — track headcount momentum and expansion into new countries across a portfolio or watchlist.
- **Job boards and aggregators** — pull clean, normalised jobs from many ATS platforms with one schema.

### How to use

1. Add companies: names, domains, careers page URLs or job board URLs — one per line.
2. Choose the output: **companies + jobs** (default), jobs only, or company hiring signals only. Add filters if you only need certain roles.
3. Click **Start**. Download results as JSON, CSV, Excel or HTML, or connect them to Google Sheets, Clay, Make, Zapier or n8n.

Example input:

```json
{
  "companies": [
    "Notion",
    "linear.app",
    "https://careers.bunq.com"
  ],
  "output": "both",
  "jobFunctions": [
    "engineering",
    "data"
  ],
  "trackChanges": true
}
```

### Input options

| Field | What it does |
|---|---|
| `companies` | Company names, domains, careers pages or ATS board URLs. Auto-detects the platform. |
| `output` | Jobs, company hiring signals, or both. |
| `includeDescription` | Add the plain-text job description to each job. |
| `trackChanges` | Flag new and closed roles since the previous run (use with a schedule). |
| `titleKeywords / excludeTitleKeywords` | Keep or drop jobs by words in the title. |
| `jobFunctions` | Engineering, data, product, design, sales, marketing, customer, operations, finance, people, legal, security, IT, research, healthcare. |
| `seniority` | Intern, junior, mid, senior, lead, manager, principal, director, executive. |
| `locations` | Keep jobs whose location contains any of these strings. |
| `remoteOnly` | Only fully remote jobs. |
| `postedWithinDays` | Only jobs posted in the last N days. |
| `maxJobsPerCompany` | Newest jobs first, capped per company. |
| `atsPlatforms` | Limit auto-detection to specific platforms. |

### Output

Each **job** row (real example from a run):

```json
{
  "recordType": "job",
  "companyName": "Notion",
  "companyDomain": "notion.com",
  "ats": "ashby",
  "jobId": "477768e1-37af-49bc-a4de-6564e0a4ec54",
  "title": "Security Engineer, Corporate Security",
  "jobFunction": "engineering",
  "seniority": "mid",
  "department": "Security",
  "team": "Security",
  "employmentType": "FullTime",
  "workplaceType": "hybrid",
  "remote": true,
  "location": "San Francisco, California | New York, New York",
  "city": "San Francisco",
  "country": "United States",
  "countryCode": null,
  "postedAt": "2026-06-08T18:00:20.281Z",
  "daysSincePosted": 132,
  "salaryMin": 200000,
  "salaryMax": 220000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "salarySource": "text",
  "techStack": "Python, Bash, OpenAI API, LLMs, AWS, GCP, Azure, Terraform, SOC 2, ISO 27001, Okta, OAuth, Figma",
  "minYearsExperience": 5,
  "visaSponsorship": null,
  "isNewSinceLastRun": null,
  "url": "https://jobs.ashbyhq.com/notion/477768e1-37af-49bc-a4de-6564e0a4ec54",
  "applyUrl": "https://jobs.ashbyhq.com/notion/477768e1-37af-49bc-a4de-6564e0a4ec54/application",
  "careersUrl": "https://jobs.ashbyhq.com/notion",
  "scrapedAt": "2026-10-19T09:58:05.109Z"
}
```

Each **company** row (real example from a run):

```json
{
  "recordType": "company",
  "companyName": "Notion",
  "companyDomain": "notion.com",
  "ats": "ashby",
  "careersUrl": "https://jobs.ashbyhq.com/notion",
  "openJobs": 129,
  "matchingJobs": 129,
  "jobsPostedLast7Days": 7,
  "jobsPostedLast30Days": 31,
  "jobsPostedLast90Days": 103,
  "hiringTrend": "steady",
  "newJobsSinceLastRun": null,
  "closedJobsSinceLastRun": null,
  "engineeringShare": 38,
  "salesAndMarketingJobs": 48,
  "leadershipJobs": 8,
  "remoteShare": 0,
  "topFunctions": "engineering (46), sales (41), people (11), finance (7), marketing (7), customer (4)",
  "topDepartments": "Sales (44), People (16), Engineering (14), Outcomes Architect (14), Early Career (8), Finance (8)",
  "seniorityMix": "mid (68), manager (24), principal (17), lead (6), director (5), executive (3), intern (3), senior (2), junior (1)",
  "topLocations": "San Francisco, California (66), New York, New York (46), Tokyo, Japan  (18), Dublin, Ireland (17), Paris, France (6), London, United Kingdom (5), Seoul, South Korea (5), Munich, Germany (3)",
  "countries": "United States, Japan, Ireland, France, South Korea, United Kingdom, Germany, India, Australia",
  "techStack": "Python, Salesforce, TypeScript, SQL, Node.js, LLMs, React, JavaScript, AWS, Java, PostgreSQL, GCP, Azure, MySQL, Slack, Workday, RAG, OpenAI API, Figma, CI/CD, NetSuite, Kubernetes, OAuth, Elasticsearch, Rust",
  "techStackCounts": "Python (16), Salesforce (15), TypeScript (14), SQL (12), Node.js (12), LLMs (12), React (9), JavaScript (7), AWS (7), Java (6), PostgreSQL (6), GCP (5), Azure (5), MySQL (5), Slack (5), Workday (5), RAG (4), OpenAI API (4), Figma (4), CI/CD (4), NetSuite (4), Kubernetes (3), OAuth (3), Elasticsearch (3), Rust (3)",
  "salaryMin": 85000,
  "salaryMax": 400000,
  "salaryCurrency": "USD",
  "jobsWithSalary": 90,
  "newestJobPostedAt": "2026-10-19T02:21:21.108Z",
  "oldestJobPostedAt": "2025-07-25T22:00:31.199Z",
  "latestJobTitles": "Sales Strategy & Operations Manager, APAC | Product Manager, Connections | Lifecycle Marketing Manager, Campaign Strategy & Execution | Recruiting Coordinator, EMEA | Recruiting Coordinator, Tokyo",
  "signals": "7 new roles posted in the last 7 days • Hiring 46 engineering roles • Hiring 41 sales roles • Hiring 11 people/HR roles • Leadership hiring: General Manager, DACH; Head of Early Career Recruiting; Head of Demand Engine • Go-to-market expansion: 48 sales/marketing roles (37% of openings) • Hiring across 9 countries",
  "companyDescription": null,
  "scrapedAt": "2026-10-19T09:58:05.109Z"
}
```

Field notes:

- `jobFunction`, `seniority` and `techStack` are inferred from the title, department and description with deterministic rules — no AI guesswork, same input gives the same output.
- `salary*` fields come from the platform's structured pay data when available (`salarySource: "structured"`), otherwise from salary ranges written in the job text (`salarySource: "text"`).
- `isNewSinceLastRun` and the company `newJobsSinceLastRun` / `closedJobsSinceLastRun` are filled when **Track changes** is on and a previous run exists.

### Pricing

**Free during launch.** You pay only Apify's own platform usage, which is tiny for this actor: it reads public job-board feeds over plain HTTP, with no browser and no proxies (a typical small run uses well under $0.01 of platform credit).

Pay-per-result pricing will be introduced later; Apify notifies existing users in advance of any pricing change.

### Use it from code

Run the actor and get the results in one call (replace `<YOUR_TOKEN>` with your Apify API token):

```bash
curl -X POST "https://api.apify.com/v2/acts/kunnu_data~hiring-signals/run-sync-get-dataset-items?token=<YOUR_TOKEN>" \
  -H "Content-Type: application/json" \
  -d '{"companies":["Notion","linear.app","https://careers.bunq.com"],"output":"both","jobFunctions":["engineering","data"],"trackChanges":true}'
```

```javascript
import { ApifyClient } from 'apify-client';

const client = new ApifyClient({ token: '<YOUR_TOKEN>' });
const run = await client.actor('kunnu_data/hiring-signals').call({"companies":["Notion","linear.app","https://careers.bunq.com"],"output":"both","jobFunctions":["engineering","data"],"trackChanges":true});
const { items } = await client.dataset(run.defaultDatasetId).listItems();
console.log(items.length, items[0]);
```

```python
from apify_client import ApifyClient

client = ApifyClient("<YOUR_TOKEN>")
run = client.actor("kunnu_data/hiring-signals").call(run_input={"companies":["Notion","linear.app","https://careers.bunq.com"],"output":"both","jobFunctions":["engineering","data"],"trackChanges":True})
for item in client.dataset(run["defaultDatasetId"]).iterate_items():
    print(item)
```

### Run it daily and get only what changed

1. Save your input as a **Task** (Actor page → *Save as a new task*) with **Track changes** turned on.
2. In **Schedules**, run the task daily or weekly.
3. Each job then has `isNewSinceLastRun`, and each company row has `newJobsSinceLastRun` / `closedJobsSinceLastRun`. Connect the task to Google Sheets, Slack or a webhook to get alerts.

### Integrations and API

- **Google Sheets, Clay, Make, Zapier, n8n, Airbyte** via Apify integrations.
- **REST API and SDKs** (JavaScript, Python) — run the actor and fetch the dataset programmatically.
- **AI agents (MCP)** — the actor can be called by AI agents through the Apify MCP server; inputs and outputs are fully described by schemas.
- **Schedules** — run daily with *Track changes* on to get only what changed.

### FAQ

**Is this legal?** The actor reads only **publicly published job postings** from official public job-board feeds — no login, no private data, no personal contact details. You are responsible for using the data in line with applicable laws and the terms of the sites involved.

**How does company detection work?** For a URL, the actor reads the careers page and finds the embedded job board. For a name or domain, it checks the 8 supported platforms and keeps the matching board with the most jobs (preferring boards whose job links point at the domain you gave).

**A company was not found — why?** It may use a platform not covered yet (e.g. Workday, iCIMS) or a board name that differs from its brand. Paste the careers page URL instead of the name. Unresolved inputs are listed with reasons in the `RUN_SUMMARY` record of the run's key-value store.

**How fresh is the data?** Live — every run reads the job boards at that moment.

**Something broke or you need a field?** Open an issue on the actor's Issues tab — every report is reviewed and fixes are prioritised.

### Related actors

- [Workable Jobs Scraper – Search All Workable Jobs](https://apify.com/kunnu_data/workable-jobs-scraper)
- [SmartRecruiters Jobs Scraper](https://apify.com/kunnu_data/smartrecruiters-jobs-scraper)
- [Recruitee Jobs Scraper](https://apify.com/kunnu_data/recruitee-jobs-scraper)
- [Personio Jobs Scraper](https://apify.com/kunnu_data/personio-jobs-scraper)
- [Teamtailor Jobs Scraper](https://apify.com/kunnu_data/teamtailor-jobs-scraper)
- [SEEK Jobs Scraper – Australia & New Zealand](https://apify.com/kunnu_data/seek-jobs-scraper)
- [Dice Jobs Scraper – US Tech Jobs](https://apify.com/kunnu_data/dice-jobs-scraper)
- [Google Trends Scraper – Interest, Regions & Related Queries](https://apify.com/kunnu_data/google-trends-scraper)

# Actor input Schema

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

One per line: a company name ("Notion"), a domain ("linear.app"), a careers page URL, or a job board URL. The actor finds the company's public job board on Greenhouse, Lever, Ashby, Workable, Recruitee, SmartRecruiters, Personio, Teamtailor automatically.

## `output` (type: `string`):

Jobs = one row per open job. Companies = one hiring-signal row per company (velocity, departments, tech stack, salaries). Both = company rows plus their jobs.

## `includeDescription` (type: `boolean`):

Adds the plain-text job description to each job row (larger dataset).

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

Remembers job IDs per company in a named key-value store in your account. On the next run each job gets isNewSinceLastRun and each company row gets new/closed counts. Ideal with a daily schedule.

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

Keep jobs whose title contains at least one of these (case-insensitive).

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

Drop jobs whose title contains any of these.

## `jobFunctions` (type: `array`):

Keep only these functions (inferred from title and department).

## `seniority` (type: `array`):

Keep only these seniority levels (inferred from title).

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

Keep jobs whose location contains any of these, e.g. "London", "Germany", "US".

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

Keep only fully remote jobs.

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

Keep jobs posted in the last N days. 0 or empty = any age.

## `maxJobsPerCompany` (type: `integer`):

Newest jobs first. Company signal rows always use every open job that was fetched.

## `atsPlatforms` (type: `array`):

Limit auto-detection to these platforms. Empty = all.

## Actor input object example

```json
{
  "companies": [
    "Notion",
    "linear.app",
    "https://apply.workable.com/huggingface/",
    "https://careers.bunq.com"
  ],
  "output": "both",
  "includeDescription": false,
  "trackChanges": false,
  "remoteOnly": false,
  "maxJobsPerCompany": 1000
}
```

# Actor output Schema

## `jobs` (type: `string`):

No description

## `companies` (type: `string`):

No description

## `allResults` (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 = {
    "companies": [
        "Notion",
        "linear.app",
        "https://apply.workable.com/huggingface/",
        "https://careers.bunq.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("kunnu_data/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": [
        "Notion",
        "linear.app",
        "https://apply.workable.com/huggingface/",
        "https://careers.bunq.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("kunnu_data/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": [
    "Notion",
    "linear.app",
    "https://apply.workable.com/huggingface/",
    "https://careers.bunq.com"
  ]
}' |
apify call kunnu_data/hiring-signals --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,kunnu_data/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/AJ084cPjzVQF89Shn/builds/yrddfhkt4db9cQkzA/openapi.json
