# Job Board & ATS Finder by Company (Greenhouse, Lever, Ashby) (`vellumlabs/ats-job-board-finder`) Actor

Turn company names or websites into their public job board: which ATS (Greenhouse, Lever, Ashby, Workable, SmartRecruiters), the board slug and URL, open-job count and confidence. Reads the careers page and verifies against the vendors' public APIs. Output plugs into ATS Jobs Feed.

- **URL**: https://apify.com/vellumlabs/ats-job-board-finder.md
- **Developed by:** [Vellum Kasane](https://apify.com/vellumlabs) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $5.00 / 1,000 job board founds

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

## Job Board & ATS Finder by Company (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee, Personio)

Give it **company names or websites** and get back **where each company's public job board lives**: the ATS vendor (Greenhouse, Lever, Ashby, Workable, SmartRecruiters, Recruitee or Personio), the **board slug**, the board URL and API URL, the **number of open jobs**, sample titles and a **confidence level**. Every answer is verified against the vendor's public job-board API, so a `found: true` record is a live board you can pull jobs from right away.

Typical questions it answers:

- "Which ATS does Notion use, and what is their board slug?" -> `ashby` / `notion` / 128 open jobs.
- "Give me the Greenhouse, Lever and Ashby slugs for these 300 companies so I can watch their hiring."
- "Which of my target accounts use an ATS I cannot read (Workday, iCIMS, Taleo, SuccessFactors...)?"

The output is designed to feed the [ATS Jobs Feed](https://apify.com/vellumlabs/ats-job-boards-feed) Actor: each record carries a `feed_input` object (`{ "ats": "ashby", "slug": "notion" }`) that you can paste straight into its `companies` input to get every job as Markdown, with a new / updated / closed diff on a schedule.

### Output example

One dataset record per company (JSON, CSV, Excel or HTML download):

```json
{
    "query": "Notion",
    "company_name": "Notion",
    "website": null,
    "found": true,
    "ats": "ashby",
    "slug": "notion",
    "region": null,
    "board_url": "https://jobs.ashbyhq.com/notion",
    "api_url": "https://api.ashbyhq.com/posting-api/job-board/notion",
    "board_name": null,
    "open_jobs": 128,
    "confidence": "medium",
    "evidence": ["api-probe:ashby:notion"],
    "sample_titles": ["Account Executive, Mid-Market", "Software Engineer, Infrastructure", "Product Designer"],
    "other_boards": [
        {
            "ats": "workable",
            "slug": "notion",
            "open_jobs": 0,
            "confidence": "medium",
            "board_name": "Notion",
            "board_url": "https://apply.workable.com/notion/"
        }
    ],
    "ats_hints": [],
    "other_ats": [],
    "feed_input": { "ats": "ashby", "slug": "notion" },
    "pages_read": [],
    "pages_skipped_by_robots": [],
    "slugs_tried": ["notion"],
    "probes": 5,
    "errors": [],
    "fetched_at": "2026-09-28T04:30:12.000Z"
}
```

### Pricing

Pay-per-event. You pay per company checked, never per request the Actor makes on your behalf:

| Event             | Price                  | When                                                                                                             |
| ----------------- | ---------------------- | ---------------------------------------------------------------------------------------------------------------- |
| `board-found`     | **$0.005** per company | The company resolved to a live board (verified on the vendor API) with open jobs, or linked from its own site.   |
| `company-checked` | **$0.001** per company | Every vendor was checked and no board was found. The record is still written (with `ats_hints` and `other_ats`). |
| Actor start       | $0.01 per run          | Apify's standard start event.                                                                                    |

A list of 200 companies of which 150 resolve costs about $0.81. Use **Max total charge per run** to hard-cap spend; the Actor stops gracefully before exceeding it.

### How to find a company's job board and ATS

1. Paste company names, domains or careers-page URLs into **Companies** (one JSON array). Strings are enough: `"PostHog"`, `"blueground.com"`, `"https://linear.app/careers"`. Objects add hints: `{ "name": "GitLab", "website": "about.gitlab.com", "slugs": ["gitlab-inc"], "ats": "greenhouse" }`.
2. Click **Start**. For every company the Actor:
   - reads up to 5 pages of the company's own website when you gave one (home, `/careers`, `/jobs`, plus careers links found on the home page), respecting `robots.txt`, and extracts links to the five vendors' hosted boards;
   - derives board-slug guesses from the name and domain (`Hugging Face` -> `huggingface`, `hugging-face`, `hugging`; `about.gitlab.com` -> `gitlab`) and probes each vendor's public job-board API with them;
   - keeps the boards the vendors confirm, grades the confidence, and picks the best one (boards with open jobs first, then confidence, then size).
3. Open the **Output** tab or download the dataset. `SUMMARY.json` in the key-value store lists every company with the result and the number of probes.

Runs are fast: about 1-3 seconds per company with a website, under a second without.

### Input

| Field                 | Type    | Default  | Notes                                                                                                                                                          |
| --------------------- | ------- | -------- | -------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `companies`           | array   | required | Strings (`"Acme"`, `"acme.com"`, `"https://acme.com/careers"`) and/or objects `{ name, website, slugs, ats }`. Duplicates (same name + host) are checked once. |
| `atsList`             | array   | all seven | Restrict to some vendors, e.g. `["greenhouse", "lever"]`.                                                                                                      |
| `probeWebsite`        | boolean | `true`   | Read the company site for board links (only when a website is given).                                                                                          |
| `maxSlugGuesses`      | integer | 4        | Slug variants tried per vendor. Raise to 6-8 for companies with long or unusual names.                                                                         |
| `includeSampleTitles` | boolean | `true`   | Include up to 5 job titles per board, useful to confirm it is the right company when the slug is generic.                                                      |
| `maxCompanies`        | integer | 100      | Hard cap per run (also caps your cost).                                                                                                                        |

### Output fields

| Field                                                                          | Meaning                                                                                                                                                                                                                                                                                           |
| ------------------------------------------------------------------------------ | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| `found`                                                                        | `true` when a live board with open jobs was verified on a vendor API, or the company's site links to a (possibly empty) board.                                                                                                                                                                    |
| `ats`, `slug`, `region`                                                        | Best board. `region` is `eu` for Lever EU boards (`jobs.eu.lever.co`).                                                                                                                                                                                                                            |
| `board_url` / `api_url`                                                        | The vendor-hosted careers page and the public JSON endpoint that verified it.                                                                                                                                                                                                                     |
| `board_name`                                                                   | Company name as the vendor publishes it. Only Greenhouse, Workable and SmartRecruiters expose it; Lever and Ashby return `null`.                                                                                                                                                                  |
| `open_jobs`                                                                    | Listed jobs on the board at fetch time (Ashby: listed only; SmartRecruiters: `totalFound`).                                                                                                                                                                                                       |
| `confidence`                                                                   | `high`: linked from the company's own site, or the vendor's board name matches the company name. `medium`: slug equals the normalised name or domain, or the site references the vendor. `low`: a live board on a guessed slug with nothing else. Boards with 0 open jobs are capped at `medium`. |
| `evidence`                                                                     | `website-link:<page>`, `api-probe:<ats>:<slug>`, `website-hint:<ats>`.                                                                                                                                                                                                                            |
| `other_boards`                                                                 | Other live boards for the company (a dormant Workable account, a second Greenhouse board, ...), same fields.                                                                                                                                                                                      |
| `ats_hints`                                                                    | Vendors referenced on the website without a resolvable slug (e.g. an embedded Greenhouse widget on a custom domain).                                                                                                                                                                              |
| `other_ats`                                                                    | Unsupported vendors detected on the website: `workday`, `icims`, `taleo`, `successfactors`, `bamboohr`, `personio`, `recruitee`, `teamtailor`, `jobvite`, `breezy`, `rippling`, `jazzhr`, `join`, `welcometothejungle`, `pinpoint`, `dover`, `hibob`, `freshteam`.                                |
| `feed_input`                                                                   | `{ ats, slug[, region] }` for the ATS Jobs Feed Actor.                                                                                                                                                                                                                                            |
| `pages_read` / `pages_skipped_by_robots` / `slugs_tried` / `probes` / `errors` | What the Actor did for this company, for auditing. A company with `errors` may still be found.                                                                                                                                                                                                    |

### Limitations (read before you rely on it)

- **Seven vendors only.** Companies on Workday, iCIMS, Taleo, SuccessFactors, BambooHR, Teamtailor, Jobvite and similar are reported as `found: false` with the vendor in `other_ats` when their website reveals it. There is no public job-board API to verify those.
- **Slug guessing is heuristic.** A company whose board slug is unrelated to its name (`acme-corp-2019`) and whose website does not link to the board will not be found. Give the website (best), or pass the slug in `slugs`.
- **Name collisions.** A live board on a guessed slug can belong to another company with the same name. Check `confidence`, `board_name` and `sample_titles`; prefer `high`.
- **Dormant accounts.** Many companies keep an old account on a second vendor (often Workable) with zero jobs. A board with 0 open jobs counts as found only when the company's own website links to it; otherwise it is listed in `other_boards`, the record is `found: false` and billed as `company-checked`.
- **SmartRecruiters** answers every company id with an empty list, so a SmartRecruiters board with **zero open postings cannot be detected** and is reported as not found.
- **Websites are read politely, not rendered.** Up to 5 pages per company, no JavaScript execution, `robots.txt` honoured (`User-agent: ats-job-board-finder` or `*`), one request at a time per site. Careers pages that only render the board via JavaScript contribute nothing; the API probes still run.
- **Rate limits.** The vendors do not document limits on these endpoints. The Actor makes at most `maxSlugGuesses x 5` small requests per company, three companies at a time, and retries 429 / 5xx with backoff. Runs with thousands of companies take a few minutes; lists above 5,000 must be split.
- **No proxies, no logins, no personal data.** Only public job-board endpoints and public web pages are read.

### Tips

- **Bulk mapping**: paste a column of domains from your CRM; a website beats a name because the careers page is read first.
- **Only Greenhouse and Lever slugs**: set `atsList` to `["greenhouse", "lever"]` to halve the probes.
- **Chain into a feed**: a second Actor run of [ATS Jobs Feed](https://apify.com/vellumlabs/ats-job-boards-feed) with `companies` = the `feed_input` values (filter `found == true`) turns the list into a scheduled new / updated / closed job feed.
- **Fast triage of unsupported vendors**: `probeWebsite: true`, then filter the dataset on `other_ats` to see who is on Workday or SuccessFactors.

### Data sources

| Vendor          | Endpoint probed                                                                      | Documentation                                              |
| --------------- | ------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| Greenhouse      | `GET https://boards-api.greenhouse.io/v1/boards/{slug}/jobs` and `/v1/boards/{slug}` | https://docs.greenhouse.io/job-board.html                  |
| Lever           | `GET https://api.lever.co/v0/postings/{slug}?mode=json` (EU: `api.eu.lever.co`)      | https://github.com/lever/postings-api                      |
| Ashby           | `GET https://api.ashbyhq.com/posting-api/job-board/{slug}`                           | https://developers.ashbyhq.com/docs/public-job-posting-api |
| Workable        | `GET https://apply.workable.com/api/v1/widget/accounts/{slug}`                       | https://workable.readme.io/reference/jobs-1                |
| SmartRecruiters | `GET https://api.smartrecruiters.com/v1/companies/{slug}/postings?limit=5`           | https://developers.smartrecruiters.com/docs/endpoints      |
| Recruitee       | `GET https://{slug}.recruitee.com/api/offers/`                                        | https://docs.recruitee.com/reference/offers | Careers Site API, no key. 404 for unknown companies. Custom careers domains (`careers.example.com`) are not recognised as Recruitee links; the slug guess still finds them. |
| Personio        | `GET https://{slug}.jobs.personio.de/xml` (or `.jobs.personio.com`)                   | https://developer.personio.de/docs/retrieving-open-job-positions | Public XML feed, no key. Unknown companies redirect to personio.com; the redirect is not followed and counts as "no board". |

All endpoints are public and documented by the vendors; no API keys are needed or accepted.

### Verified

Version 0.2 (2026-10-02): Recruitee and Personio added to the probes and the careers-page link patterns (shared code with ATS Jobs Feed 0.4). Local run with the prefill input plus `{ "name": "Channable", "website": "channable.com" }` and `{ "name": "Personio", "website": "personio.com" }` and `"bunq"` (11 companies): **11 found, 0 not found** in about 10 seconds; Channable -> `recruitee:channable` (10 open jobs, high, link found on channable.com), bunq -> `recruitee:bunq` (14, high), Personio -> `personio:personio` (1, medium). The eight original companies resolved exactly as in 0.1. Unit tests: 12.

Local run on 2026-09-28 with `apify run --purge` (Apify CLI 1.10, SDK 3.7.2, Node 24), prefill input (8 companies): all 8 resolved in about 5 seconds - `PostHog` -> ashby (8 jobs), `Linear` -> ashby (30), `https://stripe.com` -> greenhouse (699, `high`), `blueground.com` -> workable (10, `high`), `SmartRecruiters` -> smartrecruiters (1), `GitLab` -> greenhouse (200, `high`), `Spotify` -> lever (80), `Notion` -> ashby (128). Dormant Workable accounts with 0 jobs existed for six of the eight names and were correctly ranked into `other_boards`. Unit tests: `npm test` (11 tests: website parsing, slug candidates, careers-page link extraction, robots.txt rules, confidence and ranking).

### Support

Open an issue on the Actor's **Issues** tab. Issues are answered within one business day; fixes ship as new builds without changing the input schema.

Made by Vellum Labs. Part of the same family as [ATS Jobs Feed](https://apify.com/vellumlabs/ats-job-boards-feed) (jobs from the boards this Actor finds) and [HN Threads & Hiring](https://apify.com/vellumlabs/hn-threads-and-hiring).

# Actor input Schema

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

Company names (`"PostHog"`), websites (`"posthog.com"`, `"https://linear.app/careers"`) or objects `{ "name": "Acme", "website": "acme.com", "slugs": ["acme-inc"], "ats": "greenhouse" }` (`slugs` and `ats` are optional hints). A website gives the best results: the careers page is read for board links before guessing.

## `atsList` (type: `array`):

Restrict the search to these vendors. Default: all seven.

## `probeWebsite` (type: `boolean`):

When a website is given (or the entry is a domain), fetch up to 5 pages of it (home, /careers, /jobs and careers links found on the home page, robots.txt respected) to find board links. Turn off to rely on slug guessing only.

## `maxSlugGuesses` (type: `integer`):

How many board-slug variants derived from the name / domain are probed on every vendor (e.g. `hugging face` -> `huggingface`, `hugging-face`, `hugging`). Each guess is one small request per vendor.

## `includeSampleTitles` (type: `boolean`):

Add up to 5 job titles from the board to each record, so you can confirm the board really belongs to the company.

## `maxCompanies` (type: `integer`):

Hard cap on companies checked in one run. Each company is one billing event (`board-found` or `company-checked`), so this also caps your cost.

## Actor input object example

```json
{
  "companies": [
    "PostHog",
    "Linear",
    "https://stripe.com",
    "blueground.com",
    "SmartRecruiters",
    {
      "name": "GitLab",
      "website": "about.gitlab.com"
    },
    "Spotify",
    "Notion"
  ],
  "atsList": [
    "greenhouse",
    "lever",
    "ashby",
    "workable",
    "smartrecruiters",
    "recruitee",
    "personio"
  ],
  "probeWebsite": true,
  "maxSlugGuesses": 4,
  "includeSampleTitles": true,
  "maxCompanies": 8
}
```

# Actor output Schema

## `boards` (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 = {
    "companies": [
        "PostHog",
        "Linear",
        "https://stripe.com",
        "blueground.com",
        "SmartRecruiters",
        {
            "name": "GitLab",
            "website": "about.gitlab.com"
        },
        "Spotify",
        "Notion"
    ],
    "maxCompanies": 8
};

// Run the Actor and wait for it to finish
const run = await client.actor("vellumlabs/ats-job-board-finder").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": [
        "PostHog",
        "Linear",
        "https://stripe.com",
        "blueground.com",
        "SmartRecruiters",
        {
            "name": "GitLab",
            "website": "about.gitlab.com",
        },
        "Spotify",
        "Notion",
    ],
    "maxCompanies": 8,
}

# Run the Actor and wait for it to finish
run = client.actor("vellumlabs/ats-job-board-finder").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": [
    "PostHog",
    "Linear",
    "https://stripe.com",
    "blueground.com",
    "SmartRecruiters",
    {
      "name": "GitLab",
      "website": "about.gitlab.com"
    },
    "Spotify",
    "Notion"
  ],
  "maxCompanies": 8
}' |
apify call vellumlabs/ats-job-board-finder --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,vellumlabs/ats-job-board-finder"
        }
    }
}
```

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/Pi9a7dcB2g5ispTjc/builds/mIaATNOduFlv9TVXL/openapi.json
