# Company Jobs Watcher: New & Closed Roles by Company (`hirepulse/company-jobs-watcher`) Actor

Watch up to 50 company job boards for new and closed roles. Bring previous job IDs or save snapshots for daily monitoring. Pay $0.01 per changed company or first baseline; unchanged and no-board checks are free.

- **URL**: https://apify.com/hirepulse/company-jobs-watcher.md
- **Developed by:** [HirePulse](https://apify.com/hirepulse) (community)
- **Categories:** Jobs, Lead generation, Agents
- **Security:** Limited permissions
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$10.00 / 1,000 changed company or first baselines

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 Jobs Watcher

Monitor up to 50 company job boards and see which job IDs appeared or disappeared since your last successful check. Use it for recruiting research, account monitoring, or a daily n8n/Make workflow.

Pay **$0.01 per changed company or first baseline**. An unchanged company or a company with no supported board is free. There is no Actor start fee or dataset-item fee, and this Actor does not pass platform usage charges to the user. Your separate storage, integrations, or other account services may have their own costs.

### First run

```json
{
  "domains": ["ramp.com", "linear.app", "stripe.com"]
}
```

Each found board produces a `baseline`. Current listings are in `baseline_jobs`, and the full ID list is in `current_job_ids`. `new_jobs` is empty on a baseline: a first observation does not prove that a role just opened.

The default dataset contains one result per normalized company domain. The `NEXT_INPUT` record in the default key-value store contains the complete input for the next check, including the correct `known_job_ids` map. Copy that whole record, rather than a shortened display example. An explicit empty ID array means the previous board was empty; an absent domain key means no baseline yet.

### Real captured output

Selected summary fields from Apify validation run `9V4K5sBt1rwVU5cg7`, captured 2026-10-30T21:35:04.648808+00:00. The full record also contains `current_job_ids` and job objects with source IDs, titles, locations, and application links. Counts change over time; this is a dated example, not a current measurement.

```json
{
  "domain": "linear.app",
  "status": "baseline",
  "ats_type": "ashby",
  "board_slug": "Linear",
  "checked_at": "2026-10-30T21:35:04.648808+00:00",
  "total_jobs": 31,
  "new_jobs_count": 0,
  "closed_jobs_count": 0,
  "new_jobs": [],
  "closed_jobs": [],
  "charged": true
}
```

### Scheduled daily monitoring

Use saved state so a fixed scheduled input does not create a new baseline every day:

```json
{
  "domains": ["ramp.com", "linear.app", "stripe.com"],
  "state_key": "daily-company-watch"
}
```

Save this input as a Task. In Apify Console, create a daily schedule at 09:00 in your chosen timezone and enable exclusive execution. Keep the same `state_key` and run under the same account. Do not run the same watch concurrently. Snapshots are kept in a named key-value store scoped to the Actor, running account and watch name. A failed source check leaves the last successful snapshot untouched. If you delete that saved store, the next check creates a new paid baseline.

An explicit `known_job_ids` entry overrides saved state for that domain. For automatic schedules, omit the explicit map so each run uses the last successful saved snapshot. A fresh watch name creates a fresh baseline.

An example public Task and a **disabled** daily schedule are provided with this Actor. Review the domains, spending cap and timezone before enabling the schedule in your account. The disabled example does not run automatically.

### Results and alerts

| Status | Meaning | Charge per company |
|---|---|---:|
| `baseline` | First successful snapshot, including a verified empty board | $0.01 |
| `changed` | One or more job IDs appeared or disappeared | $0.01 |
| `unchanged` | Same set of job IDs as the supplied/saved snapshot | $0.00 |
| `not_found` | No supported board found on the inspected company pages | $0.00 |
| `error` | Blocked source, timeout, malformed/incomplete data, or spending limit | $0.00 |

The custom billing event is `company-changed`. It is charged at most once per company per run. At 50 companies the maximum event charge is $0.50. Set Apify's maximum total charge before starting. If that cap prevents a charge, the affected result is withheld, an uncharged diagnostic is returned, and saved state is not advanced.

On `changed`, `new_jobs` contains the current source records for newly observed IDs and `closed_jobs` contains disappeared IDs. Saved-state mode can also retain their previous titles and links; when you provide only IDs, missing metadata cannot be reconstructed. A disappeared listing may have been removed, migrated or reposted; it does not prove that the position was filled. Title or salary edits with the same ID do not trigger a change.

For notifications, connect Apify's completed-run integration to n8n or Make, read the dataset, and continue only for rows where `status == "changed"`. Send alerts to a destination you configure there. This Actor writes structured changes; it does not send emails or messages itself. `SUMMARY` contains per-status counts and the charged-company count; `NEXT_INPUT` helps stateless clients continue the comparison.

### API

Use Apify Console, the official Apify client, or start a run with your own Apify token:

```bash
curl -X POST \
  'https://api.apify.com/v2/acts/hirepulse~company-jobs-watcher/runs?maxTotalChargeUsd=0.50' \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H 'Content-Type: application/json' \
  --data '{"domains":["ramp.com","linear.app","stripe.com"],"state_key":"daily-company-watch"}'
```

This starts an asynchronous run. Poll its run ID, then fetch items from `defaultDatasetId` and the `NEXT_INPUT` record from `defaultKeyValueStoreId`. Keep the token private. Do not blindly repeat start requests after a network timeout; first check whether a run was created.

### Input and limits

- `domains`: required, 1–50 public company domains or HTTPS URLs. Duplicate normalized domains are checked once. Local/private targets and IP addresses are rejected.
- `known_job_ids`: optional object mapping input domains to arrays of at most 5,000 string IDs (1–128 characters each). Use a complete previous snapshot; a truncated list produces misleading differences.
- `state_key`: optional watch name, up to 64 letters, digits, hyphens or underscores. Omit or leave empty for stateless runs.
- Supported boards: Greenhouse, Lever, Ashby, Workable, Recruitee and SmartRecruiters. Discovery requires a link from the company pages; a same-name board alone is insufficient. Stripe's company index is matched to Greenhouse IDs before accepting its board.
- No Workday support, browser rendering, proxy service, login, or external paid data provider. `not_found` does not mean the company has no jobs; its board may be unsupported or invisible in fetched HTML.
- Source requests and each company check have time limits. Oversized, malformed or detectably incomplete snapshots return an error instead of claiming mass closures. Third-party sources can still change without notice.
- Typical runtime depends on the source and number of companies; there is no fixed runtime guarantee. Each company has a 75-second detection limit and up to three companies are processed concurrently.

### Related tools

Use [ATS Job Pulse](https://apify.com/hirepulse/ats-job-pulse) for richer job extraction and filtering. Company Jobs Watcher is focused on recurring ID-set changes and charges only for a baseline or a change.

# Actor input Schema

## `domains` (type: `array`):

1–50 public company domains. No hidden target is used.

## `known_job_ids` (type: `object`):

Optional map {"linear.app":\["id",...]}. Copy current_job_ids from a previous successful result. Missing key creates a baseline; an empty array means a known empty board.

## `state_key` (type: `string`):

Enable persistent snapshots for scheduled runs. Use a distinct name per watch and do not run the same watch concurrently. Explicit known_job_ids takes precedence. Leave empty for stateless operation.

## Actor input object example

```json
{
  "domains": [
    "ramp.com",
    "linear.app",
    "stripe.com"
  ],
  "state_key": ""
}
```

# Actor output Schema

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

No description

## `nextInput` (type: `string`):

No description

## `summary` (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 = {
    "domains": [
        "ramp.com",
        "linear.app",
        "stripe.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("hirepulse/company-jobs-watcher").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 = { "domains": [
        "ramp.com",
        "linear.app",
        "stripe.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("hirepulse/company-jobs-watcher").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 '{
  "domains": [
    "ramp.com",
    "linear.app",
    "stripe.com"
  ]
}' |
apify call hirepulse/company-jobs-watcher --silent --output-dataset

```

## MCP server setup

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

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/JHnn5piBwQaaMOZxl/builds/uSOka47jvFash3lIB/openapi.json
