# ATS Jobs API - Greenhouse, Lever, Ashby, Workday & More (`blooming_gator/verified-job-boards`) Actor

Job postings straight from company career sites on 9 ATS platforms: Greenhouse, Lever, Ashby, Workday, SmartRecruiters, Workable, Recruitee, Rippling and Personio. Deduplicated across platforms, and every board checked against the vendor's own published job count so you can see what is complete.

- **URL**: https://apify.com/blooming\_gator/verified-job-boards.md
- **Developed by:** [Kaleb Confer](https://apify.com/blooming_gator) (community)
- **Categories:** Jobs, Lead generation, Automation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$2.50 / 1,000 verified job postings

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

## Verified Job Boards

Job postings from public ATS boards — **checked against the vendor's own record count, and told you either way.**

Every other job scraper hands you rows and lets you assume they're all there. This one reports, per board, whether completeness was *proven*, and says so plainly when it can't be.

### The two things buyers complain about

Look at the open issues on any job-data API and you find the same two, over and over: **duplicates** and **missing records**. Both are completeness failures, and both are handled structurally here rather than by effort.

**Missing records.** Greenhouse and SmartRecruiters publish a `total` alongside the board. Every fetch is compared to it. A board that comes up short is flagged, not quietly included.

**Duplicates.** Companies migrating between ATS platforms run two live boards at once — the same role, two job IDs, two vendors. A vendor's ID can't see across vendors, so deduplication is on `(company, title, location)` instead. In a 799-board index this removes about 2,500 duplicate postings, roughly 6%.

### What every run returns

Alongside the roles, a `PROVENANCE` record:

```json
{
  "boards": 3,
  "boards_with_published_count": 2,
  "boards_verified_complete": 2,
  "duplicates_removed": 1,
  "unique_roles": 188,
  "detail": [
    { "company": "Stripe", "ats": "greenhouse", "postings_fetched": 566,
      "count_published_by_vendor": 566, "verified_complete": true,
      "completeness_basis": "vendor count matched" },
    { "company": "Ramp", "ats": "ashby", "postings_fetched": 136,
      "count_published_by_vendor": null, "verified_complete": null,
      "completeness_basis": "vendor publishes no count; whole board returned in one call" }
  ]
}
```

Note the `null` on Ramp. Ashby doesn't publish a count, so completeness there is **credible but not proven** — one call returns the whole board, with no pagination to truncate. It is reported as unknown rather than dressed up as verified. That distinction is the entire point.

### Input

| Field | Description |
|---|---|
| `companies` | Company names. Board tokens resolve automatically — `Stripe` finds `greenhouse/stripe`. |
| `keyword` | Optional title filter. |
| `platforms` | Which ATS platforms to check. Default: greenhouse, ashby, lever. |
| `maxResults` | `0` for no limit. |

### Supported platforms

| Platform | Completeness provable? |
|---|---|
| Greenhouse | **yes** — publishes `meta.total` |
| SmartRecruiters | **yes** — publishes `totalFound` |
| Ashby | whole board in one call, no count published |
| Lever | whole board in one call, no count published |
| Workable | whole board in one call, no count published |
| Recruitee | whole board in one call, no count published |

### Why not LinkedIn

Measured, not assumed. LinkedIn's public guest endpoint returns **30 unique postings** for a broad query and goes empty at offset 600, with no total anywhere in the response. You cannot prove a corpus complete against a source that won't tell you how big it is.

Every endpoint used here is the ATS vendor's own documented public API: no login, no session cookie, no terms accepted, no CAPTCHA, no IP-block circumvention. A board token either resolves or returns 404. Postings contain company data, not personal data of private individuals.

### Cost

Pay per result. You are charged for unique, deduplicated roles delivered — not for the run, and not for the duplicates that were removed before you saw them.

# Actor input Schema

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

Company names. Board tokens are resolved automatically - 'Stripe' finds greenhouse/stripe.

## `keyword` (type: `string`):

Optional. Only return roles whose title contains this text.

## `platforms` (type: `array`):

Which applicant-tracking systems to check. Greenhouse, SmartRecruiters and Workday publish a record count, so completeness can be PROVEN on those. Workday is slower (20 results per request) but covers large enterprises.

## `maxResults` (type: `integer`):

0 = no limit.

## Actor input object example

```json
{
  "companies": [
    "Stripe",
    "Figma",
    "Ramp"
  ],
  "keyword": "engineer",
  "platforms": [
    "greenhouse",
    "ashby",
    "lever"
  ],
  "maxResults": 0
}
```

# Actor output Schema

## `roles` (type: `string`):

One row per unique role. Duplicates across ATS platforms are removed before delivery and are not charged.

## `provenance` (type: `string`):

Per-board record of postings fetched, the count the vendor published, and whether the two matched. Boards whose vendor publishes no count are reported as unknown rather than assumed complete.

## `datasetView` (type: `string`):

Table view of the roles in Apify Console.

# 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",
        "Figma",
        "Ramp"
    ],
    "keyword": "engineer"
};

// Run the Actor and wait for it to finish
const run = await client.actor("blooming_gator/verified-job-boards").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",
        "Figma",
        "Ramp",
    ],
    "keyword": "engineer",
}

# Run the Actor and wait for it to finish
run = client.actor("blooming_gator/verified-job-boards").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",
    "Figma",
    "Ramp"
  ],
  "keyword": "engineer"
}' |
apify call blooming_gator/verified-job-boards --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,blooming_gator/verified-job-boards"
        }
    }
}

```

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/sNV250mmUVaLpRyEA/builds/M5VHp9EhH1KpOdLwL/openapi.json
