# Hiring Intent Scorer (`rational_opaque/hiring-intent-scorer`) Actor

Find companies whose public Greenhouse, Lever, Ashby, Workable, SmartRecruiters, and Recruitee job posts show they are buying what you sell.

- **URL**: https://apify.com/rational_opaque/hiring-intent-scorer.md
- **Developed by:** [Rational Opaque](https://apify.com/rational_opaque) (community)
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 company scoreds

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?

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 Intent Scorer

**Find companies whose public job posts show they are buying what you sell.**

Reads open roles from **Greenhouse, Lever, and Ashby**, then scores each company against your product. Pass company slugs, board URLs, or domains. Returns a 0–100 intent score, reasons, tools, competitor mentions, and a why-now pitch.

**~$5 per 1,000 companies scored** (pay-per-event). No rental. Failures are not charged.

***

### Who it's for

- SDR / AE teams building weekly target lists
- Product marketers watching competitor displacement
- Founders and GTM ops scoring inbound account lists in Clay or n8n

### What you get (one row per company)

| Field                                             | Meaning                           |
| ------------------------------------------------- | --------------------------------- |
| `score`                                           | 0–100 buying-intent score         |
| `scoreReasons`                                    | Top drivers (≥5 pts each)         |
| `whyNowPitch`                                     | Short outreach angle              |
| `icpFitScore`                                     | Keyword / competitor / role fit   |
| `openRoles` / `newRoles7d`                        | Board size + momentum             |
| `techStackMentioned` / `competitorToolsMentioned` | Stack + displacement              |
| `buyingSignals`                                   | Quotes + job URLs                 |
| `status`                                          | `ok` · `not_found` · `blocked` · `error` |

Rule-based scoring always runs. The model never sets the score. Optional LLM only rewrites `summary` / `whyNowPitch` (extra charge, cached).

### Quick start

```json
{
  "companies": ["stripe", "jobs.lever.co/plaid", "linear.app"],
  "productDescription": "Observability platform for Kubernetes teams that cuts cloud costs.",
  "icpKeywords": ["kubernetes", "observability", "cost optimization", "SRE"],
  "competitorTools": ["Datadog", "New Relic"],
  "sinceDays": 7,
  "minScore": 40,
  "llmEnrich": false
}
```

**Input tips**

| Field                | Required | Notes                                                |
| -------------------- | -------- | ---------------------------------------------------- |
| `companies`          | yes      | Slug (`stripe`), board URL, or domain (`linear.app`) |
| `productDescription` | yes      | What you sell — used in the pitch                    |
| `icpKeywords`        | no       | Case-insensitive fit terms                           |
| `competitorTools`    | no       | Mentions = displacement signal                       |
| `sinceDays`          | no       | Window for `newRoles7d` (default 7)                  |
| `onlyChanged`        | no       | Keep boards that changed since last run              |
| `minScore`           | no       | Drop weak `ok` rows (failures still returned)        |
| `llmEnrich`          | no       | Needs `LLM_API_KEY`; extra PPE events                |
| `atsProviders`       | no       | `greenhouse` · `lever` · `ashby` (default: all)      |

### Sample output (trimmed)

```json
{
  "company": "stripe",
  "status": "ok",
  "ats": "greenhouse",
  "openRoles": 142,
  "newRoles7d": 11,
  "score": 78,
  "icpFitScore": 71,
  "scoreReasons": [
    "Hiring momentum: 11 new in window, 142 open (+14)",
    "ICP keyword fit: 3 keyword(s) (+20)",
    "Competitor tools: 1 mentioned (+9)"
  ],
  "techStackMentioned": [
    { "tool": "Kubernetes", "count": 18 },
    { "tool": "AWS", "count": 12 },
    { "tool": "Terraform", "count": 7 }
  ],
  "competitorToolsMentioned": ["Datadog"],
  "whyNowPitch": "Stripe opened 11 roles this week with Kubernetes and observability language — strong timing for a cost-focused pitch to SRE leadership."
}
```

### Pricing (PPE only)

| Event                          | Price            | When                                                 |
| ------------------------------ | ---------------- | ---------------------------------------------------- |
| **`company-scored` (primary)** | **$0.005**       | `status=ok` row pushed                               |
| `job-enriched-llm`             | $0.002           | Valid job LLM JSON, not a cache hit                  |
| `company-summary`              | $0.01            | Model returns summary + whyNowPitch, not a cache hit |
| `apify-actor-start`            | platform default | Actor start                                          |

**Not charged:** `not_found`, `blocked`, `error`, rows dropped by `minScore` / `onlyChanged`, LLM cache hits, missing `LLM_API_KEY`.

Example: 1,000 scored companies ≈ **$5** (plus start fee and any optional LLM events). Creators keep ~80% of event revenue after compute.

In Console: keep `company-scored` as the primary event. Remove `apify-default-dataset-item` so failures are not double-charged.

### How scoring works (v1)

Components are clamped 0–1, then combined:

- **H** hiring momentum — new roles in window + open roles
- **R** relevant roles — share matching ICP keywords
- **K** ICP keyword fit — distinct matches
- **C** competitor mentions
- **B** buying-signal types
- **L** leadership hire (Director / VP / CxO) matching ICP in window
- **F** freshness vs last run (`hiring-state` KV store)

```
icpFitScore = round(100 * (0.45*K + 0.35*C + 0.20*R))
score       = round(100 * (0.20*H + 0.10*R + 0.20*K + 0.15*C + 0.20*B + 0.05*L + 0.10*F))
```

No open roles → score `0` and reason `no open roles`. Short tokens like `Go` / `R` use careful matching (golang, RStudio, etc.).

### Integrations

**Clay** — Apify integration → map domain/slug → `companies`. Write back `score`, `competitorToolsMentioned`, `whyNowPitch`.

**n8n** — Apify node → Run actor → same JSON input as Quick start.

### Limits

- Public Greenhouse, Lever, and Ashby boards only (HTTP JSON)
- No LinkedIn, Workday, iCIMS, or India ATS feeds
- No login, CAPTCHA bypass, email lookup, or personal data
- Domain resolve tries homepage, `/careers`, `/jobs`; blocked boards → `blocked` / `not_found`
- Login wall or CAPTCHA stops that company (no retry around it)

### FAQ

**Where does the data come from?**\
Public board APIs: `boards-api.greenhouse.io`, `api.lever.co`, `api.ashbyhq.com`. You supply the company list.

**Why not LinkedIn?**\
Out of scope for v1. These three boards already cover a lot of technical hiring with stable public JSON.

**What does `blocked` mean?**\
401/403 or a login/CAPTCHA page. That company is skipped and not charged.

**Board slugs go stale.**\
Confirm your own slugs. `leverdemo` is a live Lever board useful for smoke tests.

### Legal

Collects only publicly available job-board data from Greenhouse, Lever, and Ashby public APIs/pages. Does not log in, bypass CAPTCHAs or access controls, or collect personal data about individuals — output is company-level. You are responsible for complying with applicable law (including GDPR, CCPA, and India's DPDP Act), source terms, and anti-spam rules for outreach. Not affiliated with Greenhouse, Lever, Ashby, or any listed company. Scores and optional AI text are estimates and may be inaccurate.

# Actor input Schema

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

Each item: ATS board slug (e.g. 'stripe'), board URL (boards.greenhouse.io/x, jobs.lever.co/x, jobs.ashbyhq.com/x), or company domain (e.g. 'linear.app').

## `productDescription` (type: `string`):

1-3 sentences on what you sell. Used for ICP fit and the whyNowPitch.

## `icpKeywords` (type: `array`):

Terms that signal fit (tools, pains, projects).

## `competitorTools` (type: `array`):

Tools whose mention signals displacement opportunity.

## `sinceDays` (type: `integer`):

Count a role as new when it was posted within this many days. The output field stays newRoles7d.

## `onlyChanged` (type: `boolean`):

After the first run, hide companies whose open job ids did not change.

## `minScore` (type: `integer`):

Drop successful company rows below this score. Failed lookups are still returned.

## `llmEnrich` (type: `boolean`):

Extract tools/pains/quotes per new matching job and write summary + whyNowPitch.

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

Cap how many open jobs are fetched and scored for each company.

## `atsProviders` (type: `array`):

Public job boards to probe, in order, when the input is a slug or domain.

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "jobs.lever.co/plaid",
    "linear.app"
  ],
  "productDescription": "Observability platform for Kubernetes teams that cuts cloud costs.",
  "icpKeywords": [
    "kubernetes",
    "observability",
    "cost optimization",
    "SRE"
  ],
  "competitorTools": [
    "Datadog",
    "New Relic"
  ],
  "sinceDays": 7,
  "onlyChanged": false,
  "minScore": 0,
  "llmEnrich": false,
  "maxJobsPerCompany": 200,
  "atsProviders": [
    "greenhouse",
    "lever",
    "ashby"
  ]
}
```

# Actor output Schema

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

Scored companies from public Greenhouse, Lever, and Ashby job posts. Each item includes tools, buying signals, score, and whyNowPitch.

# 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": [
        "stripe",
        "jobs.lever.co/plaid",
        "linear.app"
    ],
    "productDescription": "Observability platform for Kubernetes teams that cuts cloud costs.",
    "icpKeywords": [
        "kubernetes",
        "observability",
        "cost optimization",
        "SRE"
    ],
    "competitorTools": [
        "Datadog",
        "New Relic"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("rational_opaque/hiring-intent-scorer").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": [
        "stripe",
        "jobs.lever.co/plaid",
        "linear.app",
    ],
    "productDescription": "Observability platform for Kubernetes teams that cuts cloud costs.",
    "icpKeywords": [
        "kubernetes",
        "observability",
        "cost optimization",
        "SRE",
    ],
    "competitorTools": [
        "Datadog",
        "New Relic",
    ],
}

# Run the Actor and wait for it to finish
run = client.actor("rational_opaque/hiring-intent-scorer").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": [
    "stripe",
    "jobs.lever.co/plaid",
    "linear.app"
  ],
  "productDescription": "Observability platform for Kubernetes teams that cuts cloud costs.",
  "icpKeywords": [
    "kubernetes",
    "observability",
    "cost optimization",
    "SRE"
  ],
  "competitorTools": [
    "Datadog",
    "New Relic"
  ]
}' |
apify call rational_opaque/hiring-intent-scorer --silent --output-dataset

```

## MCP server setup

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

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/Ju1zdQ9fYBIGLKHX9/builds/Uy2UWhlordbrChhlr/openapi.json
