# Hiring Signals Extractor (Greenhouse + Lever) (`rowcrate/hiring-signals-extractor`) Actor

Every open role from any company on Greenhouse or Lever, with stack keywords and how many roles each company has open right now.

- **URL**: https://apify.com/rowcrate/hiring-signals-extractor.md
- **Developed by:** [Nicolas](https://apify.com/rowcrate) (community)
- **Categories:** Jobs, Business
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.30 / 1,000 job rows

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?

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 Extractor (Greenhouse + Lever)

Every open role at any company that runs its hiring on Greenhouse or Lever — with the
technologies each posting mentions, and **how many roles that company has open right now**.

### Why the count matters more than the posting

One opening can be a backfill. Five at once is an approved budget and a team that is
growing — and that is a completely different conversation.

`company_open_roles` is on every row. Sort by it and you have your call list.

### What people use it for

**Recruiters and staffing firms.** Find the companies hiring for your specialism this week,
before the roles fill up.

**Agencies selling to engineering teams.** A company hiring three platform engineers is
about to have infrastructure problems worth solving.

**Competitive and market research.** What is a competitor building? Look at what they are
hiring for and where.

**Job boards and aggregators.** A clean, structured feed straight from the source, with no
scraping of a third-party board in the middle.

### What you get back

| company | ats | job\_title | department | location | remote | posted\_at | stack\_matched | company\_open\_roles |
|---|---|---|---|---|---|---|---|---|
| Acme Cloud | greenhouse | Senior Backend Engineer, Go | Engineering | Remote - US | true | 2026-09-01T18:03:11Z | go, kubernetes | 3 |
| Acme Cloud | greenhouse | Data Analyst | Data | Austin, TX | false | 2026-08-20T13:00:00Z | python | 3 |
| Beta Labs | lever | Platform Engineer (Terraform) | Infrastructure | Berlin | true | 2026-09-01T08:00:00Z | kubernetes, rust, terraform | 2 |

Also included: `job_id`, `employment_type`, `job_url`, `company_slug`, plus `source_url`,
`collected_at`, `collection_method` and `record_hash` on every row.

Dates are normalised to ISO 8601 UTC, so postings from both systems sort together correctly.

### Settings

| Setting | Default | What it does |
|---|---|---|
| **Companies to watch** | — | `greenhouse:token` or `lever:token` per company. |
| **Technologies you care about** | python, go, rust, kubernetes, terraform | Matches land in `stack_matched`. |
| **Only postings that mention one of them** | Off | Off is usually better — a company's non-engineering hiring is still a growth signal. |

#### Finding a company's token

Look at the address of their careers page:

- `boards.greenhouse.io/gitlab` → `greenhouse:gitlab`
- `jobs.lever.co/netflix` → `lever:netflix`

Many companies embed the board at `company.com/careers`; the token is usually visible in the
page source or in the "view all jobs" link. Not sure which system? Add the company both
ways — the one that does not exist is reported and ignored, and it costs a cent.

### What it costs

| Event | Price |
|---|---|
| Run started | $0.01 |
| Company checked | $0.01 |
| Job row | $0.0003 |

50 companies returning 900 postings costs about **$0.78**. Pricing is per company rather
than per posting because that is where the real cost is: a company with 80 openings takes
the same single request as one with two.

### Good to know

- **No LinkedIn, and that is deliberate.** Scraping LinkedIn behind a login violates its
  terms, gets accounts banned, and carries real legal exposure for whoever commissioned it.
  Greenhouse and Lever publish these same postings through documented public APIs — the
  lawful route, and a more reliable one, because an API does not change its markup.
- **Straight from the source.** These are the exact feeds that render each company's own
  careers page. No third-party job board in between adding delay or duplicates.
- **`robots.txt` checked and respected.** Verified 2026-09-08: `boards-api.greenhouse.io`
  disallows only `/embed/`; `api.lever.co` allows everything with `Crawl-delay: 1`. Both
  paths used here are permitted, and the crawl delay is honoured.
- **A company with no open roles is not an error.** It comes back empty, and that is itself
  a signal worth tracking over time.

### Questions?

Open an issue and I answer within 12 hours. Want this every Monday with only the new
postings and the companies whose open-role count went up? That is what I do —
**rowcrate.com**.

# Actor input Schema

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

One entry per company, written as greenhouse:token or lever:token. The token is the last part of the company's job board address - boards.greenhouse.io/gitlab becomes greenhouse:gitlab, and jobs.lever.co/netflix becomes lever:netflix. Not sure which system a company uses? Add it both ways; the one that does not exist is reported and ignored.

## `stackKeywords` (type: `array`):

Each posting is checked for these words and the matches land in a stack\_matched column. Leave empty to collect every role regardless of technology.

## `onlyMatchingStack` (type: `boolean`):

On: non-matching roles are dropped. Off: everything comes back and you filter in the spreadsheet. Off is usually better, because a company's non-engineering hiring still tells you it is growing.

## Actor input object example

```json
{
  "companies": [
    "greenhouse:stripe",
    "lever:plaid"
  ],
  "stackKeywords": [
    "python",
    "go",
    "rust",
    "kubernetes",
    "terraform"
  ],
  "onlyMatchingStack": false
}
```

# Actor output Schema

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

One row per posting: company, role, location, stack keywords, and how many roles that company has open right now.

## `runSummary` (type: `string`):

Row count, request count, and the error categories that came up. Read this first when a run looks off.

## `skipped` (type: `string`):

Targets that returned nothing and why. Showing the gap is what makes the rest of the file trustworthy.

# 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": [
        "greenhouse:gitlab",
        "lever:netflix"
    ],
    "stackKeywords": [
        "python",
        "go",
        "rust",
        "kubernetes",
        "terraform"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rowcrate/hiring-signals-extractor").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": [
        "greenhouse:gitlab",
        "lever:netflix",
    ],
    "stackKeywords": [
        "python",
        "go",
        "rust",
        "kubernetes",
        "terraform",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("rowcrate/hiring-signals-extractor").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": [
    "greenhouse:gitlab",
    "lever:netflix"
  ],
  "stackKeywords": [
    "python",
    "go",
    "rust",
    "kubernetes",
    "terraform"
  ]
}' |
apify call rowcrate/hiring-signals-extractor --silent --output-dataset

```

## MCP server setup

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

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/Ev8ts8bZxgnyCc6bT/builds/pK3U6faZgMbRURKJt/openapi.json
