# ATS Job Board Scraper — Workday, Greenhouse, Lever, Ashby (`splendorous_astrolabe_xs9/ats-jobs-workday`) Actor

- **URL**: https://apify.com/splendorous\_astrolabe\_xs9/ats-jobs-workday.md
- **Developed by:** [Mike](https://apify.com/splendorous_astrolabe_xs9) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

$1.50 / 1,000 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/platform/actors/running/actors-in-store#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

## ATS Job Board Scraper — Workday, Greenhouse, Lever, Ashby

One actor, four ATS systems, one clean schema. Feed it a list of companies (names or board URLs) and get every open job posting from **Workday**, **Greenhouse**, **Lever** and **Ashby** as normalized records — or run it in **delta mode** and get only what changed since the last run: the hiring signal itself.

### Why this one

- **Workday is first-class, not an afterthought.** Most job scrapers stop at Greenhouse/Lever because they have friendly JSON APIs. Workday hosts the careers sites of most of the Fortune 500, and this actor speaks its native `wday/cxs` JSON protocol directly: automatic tenant/shard discovery from a bare company name (`nvidia` → `nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite`), full pagination past the 20-per-page cap, and relative-date normalization.
- **Delta mode = hiring signals.** The actor persists a fingerprint of every run in a key-value store. The next delta run emits only `change: "new"` and `change: "removed"` postings. Schedule it daily against your prospect list and you have a live feed of who just started hiring for what — and which roles quietly disappeared.
- **One schema across all four sources.** No per-ATS parsing on your side, ever.

### Input (all of this is optional except `companies`)

```json
{
  "companies": [
    "stripe",
    "https://jobs.ashbyhq.com/openai",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    "lever:palantir",
    "workday:acme.wd1/AcmeCareers"
  ],
  "sources": ["greenhouse", "lever", "ashby", "workday"],
  "keywords": ["engineer", "data"],
  "locations": ["Remote", "New York"],
  "remoteOnly": false,
  "mode": "delta"
}
```

Plain names are auto-discovered on every enabled source. Companies that can't be found are reported in the log and skipped gracefully — never a crashed run.

### Output sample

```json
{
  "company": "nvidia",
  "source": "workday",
  "job_id": "JR2018037",
  "title": "Distinguished Engineer, Storage – AI Cloud",
  "department": null,
  "location": "US, CA, Santa Clara",
  "remote": null,
  "employment_type": null,
  "posted_at": "2026-08-03",
  "posted_raw": "Posted Today",
  "updated_at": null,
  "url": "https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite/job/US-CA-Santa-Clara/Distinguished-Engineer--Storage---AI-Cloud_JR2018037",
  "board_url": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
  "change": "new"
}
```

Fields not exposed by a given ATS (e.g. Workday's list API has no department) are `null`, never missing — the schema is stable.

### Use cases

- **Recruiting / sourcing intel** — watch competitors' boards; a burst of "new" senior postings is a roadmap leak.
- **Sales signals** — a company opening its first "Head of Data" or 10 sales roles is a buying trigger. Pipe delta output straight into your CRM.
- **Job aggregators** — normalized multi-ATS ingestion without maintaining four parsers.
- **Market research** — remote-work share, department mix, posting velocity across a portfolio.

### Delta mode details

State lives in the named key-value store `ats-jobs-workday-state` under `stateKey` (default `default`). Use a different `stateKey` per schedule/watchlist so they don't cross-contaminate. The first delta run seeds the baseline and emits everything as `new`. Keep the company list stable within one `stateKey` — postings of a company you removed from the input will show up once as `removed`.

### Using from Claude / MCP

Once published, call it through the Apify MCP server (`https://mcp.apify.com`):

```json
{
  "tool": "your-username/ats-jobs-workday",
  "input": {
    "companies": ["stripe", "figma"],
    "mode": "delta",
    "keywords": ["machine learning"]
  }
}
```

Ask your agent: *"Which of my target accounts started hiring ML engineers this week?"* — that's one delta run.

### Pricing

Pay-per-result: **$1.50 per 1,000 job postings**. A daily delta watch on 50 companies typically emits a few dozen records per day — pennies. A full snapshot of 50 large boards (~25k jobs) is about $37/run... which is why delta mode exists.

### Fair use & data notes

The actor only reads public, unauthenticated JSON endpoints that the career sites themselves use, with per-source rate limiting (≤ ~2 requests/second/source) and exponential backoff. Job postings are public commercial data; no candidate or personal data is touched.

# Actor input Schema

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

One entry per company. Accepts: a plain company name (e.g. <code>stripe</code> — the actor auto-discovers its board on every enabled source, including Workday tenant discovery), a full board URL (e.g. <code>https://boards.greenhouse.io/stripe</code>, <code>https://jobs.lever.co/plaid</code>, <code>https://jobs.ashbyhq.com/openai</code>, <code>https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite</code>), or an explicit <code>source:token</code> pair (e.g. <code>greenhouse:stripe</code>, <code>workday:nvidia.wd5/NVIDIAExternalCareerSite</code>).

## `sources` (type: `array`):

Which ATS systems to query. When a plain company name is given, the actor probes each enabled source for a matching board.

## `keywords` (type: `array`):

Keep only postings whose title contains at least one of these keywords (case-insensitive). Leave empty for all postings.

## `locations` (type: `array`):

Keep only postings whose location contains at least one of these strings (case-insensitive), e.g. <code>Remote</code>, <code>New York</code>, <code>London</code>. Leave empty for all locations.

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

Keep only postings flagged remote by the ATS (or whose location mentions 'remote').

## `mode` (type: `string`):

<b>snapshot</b> pushes every posting currently live. <b>delta</b> compares against this actor's previous run (persisted in a named key-value store) and pushes only postings that appeared (<code>change: "new"</code>) or disappeared (<code>change: "removed"</code>) — the hiring-signal feed. The first delta run seeds the baseline and emits everything as <code>new</code>.

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

Attach the job description (HTML) to each posting. Increases output size significantly.

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

Safety cap on postings fetched per company per source.

## `stateKey` (type: `string`):

Advanced: name of the record inside the <code>ats-jobs-workday-state</code> key-value store used for delta comparison. Change it to keep independent watchlists (one per schedule).

## Actor input object example

```json
{
  "companies": [
    "stripe",
    "https://jobs.ashbyhq.com/openai",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ],
  "sources": [
    "greenhouse",
    "lever",
    "ashby",
    "workday"
  ],
  "keywords": [],
  "locations": [],
  "remoteOnly": false,
  "mode": "snapshot",
  "includeDescription": false,
  "maxJobsPerCompany": 5000,
  "stateKey": "default"
}
```

# 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",
        "https://jobs.ashbyhq.com/openai",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("splendorous_astrolabe_xs9/ats-jobs-workday").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",
        "https://jobs.ashbyhq.com/openai",
        "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite",
    ] }

# Run the Actor and wait for it to finish
run = client.actor("splendorous_astrolabe_xs9/ats-jobs-workday").call(run_input=run_input)

# Fetch and print Actor results from the run's dataset (if there are any)
print("💾 Check your data here: https://console.apify.com/storage/datasets/" + run["defaultDatasetId"])
for item in client.dataset(run["defaultDatasetId"]).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",
    "https://jobs.ashbyhq.com/openai",
    "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"
  ]
}' |
apify call splendorous_astrolabe_xs9/ats-jobs-workday --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "command": "npx",
            "args": [
                "mcp-remote",
                "https://mcp.apify.com/?tools=splendorous_astrolabe_xs9/ats-jobs-workday",
                "--header",
                "Authorization: Bearer <YOUR_API_TOKEN>"
            ]
        }
    }
}

```

## OpenAPI specification

Download the OpenAPI definition: https://api.apify.com/v2/actors/PT5fqZvaUx5GmkRhb/builds/r3hevnXBa5Khd2YjB/openapi.json
