# Company Jobs Finder: Domain to Open Jobs, 10 ATS (`camalot/company-jobs`) Actor

Give it company websites, get every open job. Auto-detects the applicant tracking system (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio, Teamtailor, BambooHR, Rippling) and returns jobs in one unified schema, or a hiring summary per company.

- **URL**: https://apify.com/camalot/company-jobs.md
- **Developed by:** [Cameron Fagan](https://apify.com/camalot) (community)
- **Categories:** Jobs, Lead generation, AI
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

Pay per event

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 Finder: Domain to Open Jobs

Give it a list of **company websites** and get back **every open job**, without knowing which job board each company uses. The Actor finds the company's applicant tracking system (ATS) and returns all jobs in **one unified schema**, or a **hiring summary per company**.

**Supported ATS:** Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio, Teamtailor, BambooHR and Rippling.

```
stripe.com  →  Greenhouse  →  716 open jobs
notion.so   →  Ashby       →  137 open jobs
bosch.com   →  SmartRecruiters → 4,800+ open jobs
```

### Why use it

- **One input, every ATS.** Stop maintaining ten scrapers. Paste domains, get jobs.
- **Hiring signals for sales.** Find companies that are hiring for a role you sell into ("hiring 3+ data engineers" = budget for data tools). Use **Companies** output for a per-company summary with job counts by department and location.
- **Job boards and aggregators.** Pull fresh jobs from hundreds of companies on a schedule.
- **Recruiting and market research.** Track who's hiring, where, and how fast.
- **AI agents.** Clean JSON and pay-per-result pricing make it easy to call from Claude, ChatGPT, n8n, Make or Zapier ("is Acme hiring engineers in London?").

### How detection works

1. **Careers page scan:** looks at the company's homepage and careers pages for links to a supported job board. This gives `detectionConfidence: "high"`.
2. **Board-name guess:** if no link is found, tries the company's name on each ATS and keeps a board only if it has jobs and its company name matches the domain. This gives `"medium"` (name confirmed) or `"low"` (name not available).
3. Boards that belong to a different company (job aggregators, partners) are rejected.

In our tests on 45 well-known tech companies, a board was found for 38. The rest used Workday, in-house systems or ATSs not yet supported. You can also paste a job-board URL directly (e.g. `https://jobs.lever.co/palantir`).

### Input

| Field | Description |
|---|---|
| `companies` | Domains or URLs, e.g. `stripe.com`, `https://www.notion.so`, or a job-board URL. |
| `outputType` | `jobs` (one row per job) or `companies` (one row per company). |
| `titleKeywords` | Keep jobs whose title contains any of these, e.g. `engineer`, `sales`. |
| `locationKeywords` | Keep jobs whose location contains any of these, e.g. `London`, `Remote`. |
| `remoteOnly` | Only remote jobs. |
| `postedWithinDays` | Only jobs posted in the last N days. |
| `maxJobsPerCompany` | Cap per company (default 500). |
| `includeDescription` | Add full plain-text job descriptions (not available for BambooHR and Rippling). |
| `guessSlugs` | Turn the board-name guess on or off. |

### Output: jobs

```json
{
  "inputDomain": "notion.so",
  "companyName": "Notion",
  "ats": "Ashby",
  "atsSlug": "notion",
  "careersUrl": "https://www.notion.com/careers",
  "detectionMethod": "careers-page",
  "detectionConfidence": "high",
  "jobId": "1fc309c8-…",
  "title": "Software Engineer, Developer Platform",
  "department": "Engineering",
  "team": "Engineering",
  "location": "San Francisco, California",
  "locations": ["San Francisco, California", "New York, New York"],
  "country": "United States",
  "workplaceType": "hybrid",
  "isRemote": true,
  "employmentType": "FullTime",
  "postedAt": "2026-08-24T14:44:49.699Z",
  "updatedAt": null,
  "url": "https://jobs.ashbyhq.com/notion/…",
  "applyUrl": "https://jobs.ashbyhq.com/notion/…/application",
  "salary": { "min": 180000, "max": 250000, "currency": "USD", "period": "1 YEAR" },
  "description": null,
  "scrapedAt": "2026-10-04T…"
}
```

`salary` is filled when the company publishes it (common on Ashby, Lever and Recruitee). Example values are illustrative.

### Output: companies

```json
{
  "inputDomain": "stripe.com",
  "companyName": "Stripe",
  "found": true,
  "ats": "Greenhouse",
  "atsSlug": "stripe",
  "detectionConfidence": "medium",
  "openJobs": 716,
  "remoteJobs": 41,
  "byDepartment": { "Engineering": 210, "Sales": 120, "…": 0 },
  "byLocation": { "San Francisco": 150, "Dublin": 90, "…": 0 },
  "newestPostedAt": "2026-10-03T…",
  "oldestPostedAt": "2024-…",
  "jobTitles": ["Abuse Investigator", "…"]
}
```

Example values are illustrative. Companies where no supported board was found are returned with `found: false` and are **not charged**.

### Pricing

Pay per result: a small charge per company where a job board is found, plus a per-job charge in Jobs mode. No monthly fee. Set a maximum charge per run and the Actor stops cleanly when it's reached.

### FAQ

**Is this allowed?** It reads the public job feeds that these ATS platforms publish so companies can show jobs on their own websites. No logins, no personal data.

**Why wasn't a company found?** It may use Workday, iCIMS, Taleo, an in-house system, or block automated requests. Open an issue with the domain and we'll look at adding it.

**How fresh is the data?** Live at run time. Schedule the Actor daily or weekly for a hiring feed.

# Actor input Schema

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

Company domains or URLs, e.g. stripe.com, https://www.notion.so. You can also paste a job-board URL directly (e.g. https://jobs.lever.co/palantir).

## `outputType` (type: `string`):

Jobs = one row per open job. Companies = one row per company with ATS, open-job count and department/location breakdown (great for sales and hiring-signal lists).

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

Only keep jobs whose title contains any of these (case-insensitive), e.g. engineer, sales, designer.

## `locationKeywords` (type: `array`):

Only keep jobs whose location contains any of these, e.g. London, Germany, Remote.

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

Only keep jobs marked remote.

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

Only keep jobs posted in the last N days. 0 = no limit. Jobs without a posting date are excluded when this is set.

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

Upper limit of jobs returned per company.

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

Add the full plain-text job description (jobs mode). Slower for Workable and SmartRecruiters, which need one extra request per job. Not available for BambooHR and Rippling.

## `guessSlugs` (type: `boolean`):

If no job-board link is found on the company's site, try the company name as a board name on each ATS. Results are marked detectionMethod = slug-guess.

## `maxConcurrency` (type: `integer`):

How many companies to process at the same time.

## Actor input object example

```json
{
  "companies": [
    "notion.so",
    "palantir.com",
    "personio.com"
  ],
  "outputType": "jobs",
  "remoteOnly": false,
  "postedWithinDays": 0,
  "maxJobsPerCompany": 500,
  "includeDescription": false,
  "guessSlugs": true,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

One row per open job (when Output = jobs): title, department, location, workplace type, posting date, salary and apply link.

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

One row per company (when Output = companies): detected ATS, open-job count, remote jobs, department and location breakdown.

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

Which ATS was found for each input domain and how many jobs it returned.

# 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.so",
        "palantir.com",
        "personio.com"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("camalot/company-jobs").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.so",
        "palantir.com",
        "personio.com",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("camalot/company-jobs").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.so",
    "palantir.com",
    "personio.com"
  ]
}' |
apify call camalot/company-jobs --silent --output-dataset

```

## MCP server setup

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

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/VWVPcFfPhuLV0AHVZ/builds/2jGxZ08CmC8nIOXSC/openapi.json
