# Jobs Scraper for Workday, Greenhouse, Lever & Ashby (`bliseb/jobs-scraper-for-workday-greenhouse-lever-ashby`) Actor

Every open job from the career pages you follow (Greenhouse, Lever, Ashby, Workday, Recruitee, Teamtailor, Personio) as clean JSON: title, locations, remote, salary, department, apply link. Optional NEW/UPDATED/EXPIRED change feed. About $5 per 1,000 jobs.

- **URL**: https://apify.com/bliseb/jobs-scraper-for-workday-greenhouse-lever-ashby.md
- **Developed by:** [Ebblys Hernandez sierra](https://apify.com/bliseb) (community)
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $3.50 / 1,000 job posting storeds

This Actor is paid per event. You are not charged for the Apify platform usage, but only a fixed price for specific events.
Since this Actor supports Apify Store discounts, the price gets lower the higher subscription plan you have.

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

Give it the career pages of the companies you follow and get every open job as clean, normalized JSON, straight from the public endpoints of the applicant tracking systems those pages run on: **Greenhouse, Lever, Ashby, Recruitee, Teamtailor, Personio and Workday**.

- **Every posting, one format.** Title, locations, remote flag, department, employment type, posting date, salary (min/max/currency/period) when the company publishes it, full plain-text description, apply URL, job page URL. The same fields whatever the ATS.
- **Only what changed, if you want.** Turn on the change feed and each run returns only NEW, UPDATED and EXPIRED jobs compared with the previous run of the same list, ready for alerts or a job board that stays fresh.
- **Fast, cheap, no browser.** Pure HTTP against the JSON/XML feeds the career pages themselves use, with retries and back-off. **$0.005 per job — about $5 per 1,000 jobs** — nothing for expired jobs, no other charge.

Company and job data only. The actor does not extract recruiter names, e-mails, phone numbers or any other personal data; contact e-mails and phone numbers that a company pastes into a job description are removed from `descriptionText` before it is stored.

### Example output

One record per job posting, the same fields whatever the ATS. These three come from the actor's scheduled test runs of 27–29 September 2026 (nine runs, nine successes, seven career pages, up to 100 jobs each in that test), shown as the current version formats them; descriptions are cut short here, the dataset has them in full.

A Workday job (NVIDIA publishes under many legal entities; `company` is the brand, `legalEntity` the hiring entity):

```json
{
  "jobId": "workday:nvidia/nvidiaexternalcareersite:JR2023975",
  "title": "Senior Mask Layout Design Engineer",
  "company": "NVIDIA",
  "legalEntity": "TW07 NVIDIA Singapore Development PTE. Ltd. Taiwan Branch",
  "atsType": "workday",
  "locations": [
    "Taiwan, Hsinchu",
    "Taiwan, Taipei"
  ],
  "isRemote": false,
  "department": null,
  "employmentType": "full_time",
  "postedAt": "2026-09-29T00:00:00.000Z",
  "updatedAt": null,
  "salaryMin": null,
  "salaryMax": null,
  "salaryCurrency": null,
  "salaryPeriod": null,
  "descriptionText": "We are looking for a Senior Mask Layout Design Engineer – someone who is excited to join a growing group of diverse individuals responsible for handling challenging high-speed mixed-signal circuit designs.\nNVIDIA has con …",
  "applyUrl": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite/job/Taiwan-Hsinchu/Senior-Mask-Layout-Design-Engineer_JR2023975/apply",
  "sourceUrl": "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite/job/Taiwan-Hsinchu/Senior-Mask-Layout-Design-Engineer_JR2023975",
  "scrapedAt": "2026-09-29T06:30:28.191Z",
  "changeStatus": "NEW"
}
```

An Ashby job with the published pay range (`OpenAI` is derived from the board slug: Ashby exposes no board name):

```json
{
  "jobId": "ashby:openai:6c6c1ace-12d6-48f0-88f0-488ff8521571",
  "title": "IT Solutions Engineer",
  "company": "OpenAI",
  "legalEntity": null,
  "atsType": "ashby",
  "locations": [
    "San Francisco"
  ],
  "isRemote": false,
  "department": "IT",
  "employmentType": "full_time",
  "postedAt": "2026-03-06T01:23:02.602Z",
  "updatedAt": null,
  "salaryMin": 187000,
  "salaryMax": 266000,
  "salaryCurrency": "USD",
  "salaryPeriod": "year",
  "descriptionText": "About the Team\n\nIT Systems Operations serves as the operational control layer connecting Security, Engineering, and Employee Technology platforms. The team ensures employee-facing systems, identity wo …",
  "applyUrl": "https://jobs.ashbyhq.com/openai/6c6c1ace-12d6-48f0-88f0-488ff8521571/application",
  "sourceUrl": "https://jobs.ashbyhq.com/openai/6c6c1ace-12d6-48f0-88f0-488ff8521571",
  "scrapedAt": "2026-09-28T18:30:14.833Z",
  "changeStatus": "NEW"
}
```

A Recruitee job in another currency and period (monthly EUR, fixed-term contract):

```json
{
  "jobId": "recruitee:vandebron:2757993",
  "title": "Business Analyst Portfolio Management & Trading",
  "company": "Vandebron",
  "legalEntity": null,
  "atsType": "recruitee",
  "locations": [
    "Amsterdam, Noord-Holland, Nederland",
    "Vandebron HQ"
  ],
  "isRemote": false,
  "department": "Producer",
  "employmentType": "contract",
  "postedAt": "2026-09-28T07:13:32.000Z",
  "updatedAt": "2026-09-28T11:51:44.000Z",
  "salaryMin": 3000,
  "salaryMax": 3700,
  "salaryCurrency": "EUR",
  "salaryPeriod": "month",
  "descriptionText": "Wij zijn Vandebron\nOnze reis begon in 2014 met Hoofdstuk 1 van de energietransitie, waarin we de markt transparanter wilden maken door consumenten rechtstreeks te verbinden met lokale, groene energiep …",
  "applyUrl": "https://werkenbij.vandebron.nl/o/business-analyst-portfolio-management-trading/c/new",
  "sourceUrl": "https://werkenbij.vandebron.nl/o/business-analyst-portfolio-management-trading",
  "scrapedAt": "2026-09-28T12:30:12.678Z",
  "changeStatus": "NEW"
}
```

`changeStatus` appears only with the change feed on (these runs had it on): `NEW`, `UPDATED` or `EXPIRED`; an EXPIRED record keeps the last known title, company, locations and URLs plus `firstSeenAt` / `lastSeenAt`.

Export the dataset as JSON, CSV or Excel from the Apify Console, or read it through the API.

### Supported ATS and how to find the URL

Open the company's "Careers" page and look at the address bar (or the address the job listings load from). Paste that URL into **Career page URLs**; the ATS is detected automatically. You can also list boards as `ats:slug` in **Boards**.

| ATS | Typical career page URL (example verified with live data) | `boards` form |
|---|---|---|
| Greenhouse | `https://boards.greenhouse.io/stripe` or `https://job-boards.greenhouse.io/stripe` | `greenhouse:stripe` |
| Lever | `https://jobs.lever.co/palantir` (EU-hosted boards are detected automatically) | `lever:palantir` |
| Ashby | `https://jobs.ashbyhq.com/openai` | `ashby:openai` |
| Recruitee | `https://vandebron.recruitee.com` | `recruitee:vandebron` |
| Teamtailor | `https://anyfin.teamtailor.com/jobs` | `teamtailor:anyfin` |
| Personio | `https://personio.jobs.personio.de` (or `.jobs.personio.com`) | `personio:personio` (or `personio:<company>@personio.com`) |
| Workday | `https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite` | `workday:nvidia.wd5/NVIDIAExternalCareerSite` |

Tips: a career site on the company's own domain (e.g. `careers.example.com`) is usually one of these in disguise; open a job and look at where the "Apply" button goes, or view the page source for `greenhouse`, `lever.co`, `ashbyhq`, `recruitee`, `teamtailor`, `personio` or `myworkdayjobs`. Workday always needs the tenant, the `wd<N>` host and the site name, all of them in the career page URL. Career pages on other systems (iCIMS, Taleo, SuccessFactors, BambooHR, Jobvite…) are not supported yet; tell us in the Issues tab which one you need.

### What you can build with it

- **Recruiting and sourcing agencies:** watch the career pages of target accounts and know the same day when they open roles you can fill.
- **Job boards and aggregators:** feed a niche board (by industry, region or role) with structured, deduplicated postings that include apply links and, where published, salary, and let the change feed expire them when they close.
- **Labour-market and competitive intelligence:** track hiring volume, locations, remote share and published salary ranges across hundreds of companies over time.
- **Job alerts:** schedule the actor with the change feed on and push NEW jobs to Slack, e-mail or a webhook through Apify integrations.
- **Sales and investment signals:** hiring bursts in engineering, sales or a new country say a lot about a company's plans.

### Pricing

Pay per event. Two events, nothing else:

| Event | Price | When |
|---|---|---|
| `job` | **$0.005** | Each job posting stored in the dataset (NEW or UPDATED in change-feed mode) |
| `actor-start` | $0.005 | Once per run |

Examples:

- 1 company, 40 jobs → 40 × $0.005 + $0.005 = **$0.21**
- 25 companies, 1,000 jobs in total → **$5.01**
- Daily change feed over 100 companies that together post ~60 new or changed jobs a day → about **$0.31 per day**; expired jobs are free.

The price already includes the compute the actor uses; there is no extra usage charge. Set **Maximum cost per run** in the run options to cap what a run may spend: the actor stops storing jobs when the cap is reached and says so in the log. Free-plan credits work as usual.

### Input

| Field | Default | Meaning |
|---|---|---|
| `startUrls` | Palantir (Lever), Anyfin (Teamtailor), Vandebron (Recruitee) | Career page URLs (ATS detected automatically) |
| `boards` | `[]` | Boards as `ats:slug`, merged with `startUrls` |
| `includeDescription` | `true` | Add `descriptionText`. Workday needs one extra request per job for it; switching it off makes Workday boards much faster |
| `maxJobsPerCompany` | `0` (all) | Stop after this many jobs per career page |
| `onlyNewSince` | – | ISO date; drops jobs posted before it (jobs whose posting date the ATS hides are kept) |
| `changeFeed` | `false` | Report only NEW / UPDATED / EXPIRED jobs compared with the previous run |
| `stateStoreName` | `company-career-pages-jobs-state` | Named key-value store that keeps the change-feed snapshots; use one per schedule |
| `allowRobotsDisallowed` | `false` | Some ATS APIs (currently SmartRecruiters) publish a robots.txt that disallows automated access. Their career pages are skipped with a warning unless you enable this, at your own responsibility |
| `maxConcurrency` | `5` | Career pages processed in parallel |

### Change feed

With `changeFeed: true` the actor keeps one snapshot per career page in the named key-value store (`stateStoreName`), created by the actor itself on the first run, so it works with the default limited permissions. Each later run compares against it:

- **NEW** – job id not seen in the previous run (charged as `job`);
- **UPDATED** – title, locations, salary, employment type, dates or description changed (charged as `job`);
- **EXPIRED** – present before, gone now; emitted from the snapshot with `firstSeenAt` / `lastSeenAt` (**free**);
- unchanged jobs are not emitted.

The first run reports everything as NEW. Use a different `stateStoreName` for each list of companies you schedule, otherwise the lists would expire each other's jobs. If the store cannot be opened the run still completes: everything is reported as NEW and a warning explains why.

### Output fields

| Field | Type | Notes |
|---|---|---|
| `jobId` | string | Stable and globally unique: `<ats>:<company slug>:<native id>` |
| `title`, `company`, `atsType` | string | `company` is the brand name: the board name when the ATS exposes it (Greenhouse, Recruitee, Teamtailor, Personio, SmartRecruiters), otherwise derived from the board slug (`openai` → `OpenAI`, `acme-labs` → `Acme Labs`); for Workday it comes from the tenant, taking the brand's own capitalisation from the career-site name when it has it (`nvidia` + `NVIDIAExternalCareerSite` → `NVIDIA`) |
| `legalEntity` | string | null | Workday only, with `includeDescription` on (it comes from the job detail): the hiring organization exactly as the tenant publishes it (`2100 NVIDIA USA`, `IL00 Mellanox Technologies`…), useful for group companies; `null` on the other ATSs |
| `locations` | string\[] | All locations the posting lists, as written by the company |
| `isRemote` | boolean | From the ATS flag when it has one (Lever and Ashby `workplaceType`, Recruitee `remote` / `hybrid` / `on_site`, Teamtailor `TELECOMMUTE`, Workday `remoteType`); otherwise the words remote / work from home in title or locations |
| `department` | string | null | Department, team or function, when the ATS publishes it (Greenhouse, Lever, Ashby, Recruitee, Teamtailor, Personio, SmartRecruiters). The Workday endpoints we use expose no department, so it is `null` there |
| `employmentType` | enum | null | `full_time`, `part_time`, `contract`, `internship`, `temporary`, `freelance`, `other` — **when the ATS publishes it**: Ashby `employmentType`, Lever `categories.commitment`, Recruitee `employment_type_code`, Personio `employmentType` + `schedule` + `seniority`, Teamtailor schema.org `employmentType`, Workday `timeType`. Greenhouse's public API has no such field (only a custom `metadata` entry on some boards), so it is usually `null` there |
| `postedAt`, `updatedAt` | ISO 8601 | null | `updatedAt` only where the ATS provides it (Greenhouse, Lever, Recruitee, Teamtailor, SmartRecruiters); Ashby, Personio and Workday publish no update date, so it is `null` there — we never invent one |
| `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryPeriod` | number / string | null | **Structured pay data first** (Ashby `compensation`, Lever `salaryRange`, Recruitee `salary`, Greenhouse pay-transparency ranges, Personio `salaryInformation`, Teamtailor `baseSalary`). Text is only a fallback under strict rules: an explicit range with a currency symbol or code glued to the figures, never followed by "years"/"experience", within plausible bounds per period; a single figure is never a salary. Empty beats wrong. `salaryPeriod` ∈ `year`, `month`, `biweekly`, `week`, `day`, `hour` |
| `descriptionText` | string | Plain text with line breaks and bullets; contact e-mails and phone numbers removed; `""` when `includeDescription` is false |
| `applyUrl`, `sourceUrl` | string | Application form and public job page |
| `scrapedAt` | ISO 8601 | Run time |
| `changeStatus` | enum | Only in change-feed mode |

The run's key-value store also gets a `SUMMARY` record: companies processed and failed (with the error), jobs fetched, records stored, change-feed counts.

### FAQ and limits

**A company failed, does the run stop?** No. A career page that cannot be read (wrong URL, board removed, ATS outage, response that is not JSON) is logged as a warning with the reason and the other companies continue. The run fails only if every career page failed. Requests are retried with exponential back-off on 429 / 5xx and network errors.

**Are jobs deduplicated?** Yes, by `jobId` within a run.

**Change feed and `maxJobsPerCompany`.** Keep `maxJobsPerCompany` at 0 (all) when the change feed is on: with a cap, jobs that fall outside the first N of a career page are reported as EXPIRED although they are still open (the run logs a warning when both are set). Use `onlyNewSince` instead to limit what a run returns.

**Why is `postedAt` missing on some Workday jobs?** Workday's list only says "Posted 30+ Days Ago". With `includeDescription` on (the default) the exact date comes from the job detail; with it off, jobs older than 30 days have `postedAt: null`.

**How long does a run take?** Greenhouse, Lever, Ashby, Recruitee, Teamtailor and Personio return a whole board in one or a few requests (Stripe's 702 jobs take seconds). Workday returns 20 jobs per page and needs one request per job for the description, so a 2,000-job Workday tenant takes a few minutes.

**Does it work with limited permissions?** Yes. The actor only uses its own storages and a key-value store it creates itself for the change feed.

**Very large Workday tenants.** Some Workday sites cap a search at 2,000 results. Jobs beyond that are not returned in this version.

**Endpoint status.** Greenhouse (Stripe), Lever (Palantir), Ashby (OpenAI), Recruitee (Vandebron), Teamtailor (Anyfin), Personio (Personio) and Workday (NVIDIA, nine legal entities) are verified against live data in scheduled runs; report anything odd in Issues.

### Technical details

- TypeScript on Node 20 with the Apify SDK; native `fetch`, no browser, no third-party scraping libraries.
- Endpoints: Greenhouse `boards-api.greenhouse.io/v1/boards/{token}/jobs?content=true&pay_transparency=true`; Lever `api.lever.co/v0/postings/{site}?mode=json` (paginated with `skip`/`limit`, falling back to `api.eu.lever.co` only on a 404); Ashby `api.ashbyhq.com/posting-api/job-board/{board}?includeCompensation=true`; Recruitee `{company}.recruitee.com/api/offers/`; Teamtailor `{company}.teamtailor.com/jobs.json` (JSON Feed 1.1 with an embedded schema.org `_jobposting`); Personio `{company}.jobs.personio.de/xml` (XML: name, office, department, employmentType, schedule, seniority, createdAt, jobDescriptions); Workday `POST /wday/cxs/{tenant}/{site}/jobs` plus one detail request per job.
- Sources are processed with a small concurrency pool (`maxConcurrency`); Workday detail requests run 4 at a time per company.
- HTTP: 30 s timeout per request, up to 4 retries with exponential back-off honouring `Retry-After`; a 2xx whose body is not JSON is retried and then treated as a failure; other 4xx fail immediately.
- Budget: on pay-per-event runs the actor charges `actor-start` once and `job` per stored posting through the SDK, which trims a batch to what the run's maximum cost allows and stops scraping further companies once the cap is reached. Runs without pay-per-event pricing (free trials, local runs) charge nothing and say so once in the log.
- Snapshots (change feed) are JSON records named `snapshot-<ats>-<slug>` in the state store; each holds a fingerprint per job plus the fields needed to describe an expiry.
- Memory: 512 MB is plenty; a run's peak is a few tens of MB per large Workday tenant.
- Source: `actors/ats-jobs` in the repository, built by Apify from GitHub on every merge to `main`.

# Actor input Schema

## `startUrls` (type: `array`):

Career pages to scrape; the ATS is detected from the URL. Examples: https://boards.greenhouse.io/stripe, https://jobs.lever.co/palantir, https://jobs.ashbyhq.com/openai, https://vandebron.recruitee.com, https://anyfin.teamtailor.com/jobs, https://personio.jobs.personio.de, https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite

## `boards` (type: `array`):

Alternative to URLs: one board per line as `ats:slug`, e.g. `greenhouse:stripe`, `lever:palantir`, `ashby:openai`, `recruitee:vandebron`, `teamtailor:anyfin`, `personio:personio`, `workday:nvidia.wd5/NVIDIAExternalCareerSite`. Duplicates of startUrls are merged.

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

Adds the full plain-text description (`descriptionText`). For Workday this needs one extra request per job; switching it off makes those boards much faster.

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

Stop after this many jobs for each career page (0 = all). Keep it at 0 (all) when the change feed is on: with a cap, jobs beyond the first N are reported as EXPIRED although they are still open.

## `onlyNewSince` (type: `string`):

ISO date or datetime, e.g. `2026-09-01`. Jobs posted before it are dropped; jobs whose posting date the ATS does not expose are kept.

## `changeFeed` (type: `boolean`):

Compare with the previous run of the same career pages and output only what changed: new jobs (NEW), jobs whose content changed (UPDATED) and jobs that disappeared (EXPIRED, free). State is kept in the named key-value store below. The first run reports every job as NEW.

## `stateStoreName` (type: `string`):

Name of the key-value store that keeps the previous snapshot for the change feed. Use one store per schedule/list of companies.

## `allowRobotsDisallowed` (type: `boolean`):

Off by default. Some ATS APIs (currently SmartRecruiters) publish a robots.txt that disallows automated access; their career pages are skipped with a warning unless you enable this, at your own responsibility.

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

How many career pages are processed at the same time.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://jobs.lever.co/palantir"
    },
    {
      "url": "https://anyfin.teamtailor.com/jobs"
    },
    {
      "url": "https://vandebron.recruitee.com"
    }
  ],
  "boards": [],
  "includeDescription": true,
  "maxJobsPerCompany": 0,
  "changeFeed": false,
  "stateStoreName": "company-career-pages-jobs-state",
  "allowRobotsDisallowed": false,
  "maxConcurrency": 5
}
```

# Actor output Schema

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

All job postings stored by this run as JSON (append ?format=csv for CSV). In changeFeed mode each record carries changeStatus NEW, UPDATED or EXPIRED.

# 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 = {
    "startUrls": [
        {
            "url": "https://jobs.lever.co/palantir"
        },
        {
            "url": "https://anyfin.teamtailor.com/jobs"
        },
        {
            "url": "https://vandebron.recruitee.com"
        }
    ]
};

// Run the Actor and wait for it to finish
const run = await client.actor("bliseb/jobs-scraper-for-workday-greenhouse-lever-ashby").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 = { "startUrls": [
        { "url": "https://jobs.lever.co/palantir" },
        { "url": "https://anyfin.teamtailor.com/jobs" },
        { "url": "https://vandebron.recruitee.com" },
    ] }

# Run the Actor and wait for it to finish
run = client.actor("bliseb/jobs-scraper-for-workday-greenhouse-lever-ashby").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 '{
  "startUrls": [
    {
      "url": "https://jobs.lever.co/palantir"
    },
    {
      "url": "https://anyfin.teamtailor.com/jobs"
    },
    {
      "url": "https://vandebron.recruitee.com"
    }
  ]
}' |
apify call bliseb/jobs-scraper-for-workday-greenhouse-lever-ashby --silent --output-dataset

```

## MCP server setup

```json
{
    "mcpServers": {
        "apify": {
            "type": "http",
            "url": "https://mcp.apify.com/?tools=fetch-actor-details,bliseb/jobs-scraper-for-workday-greenhouse-lever-ashby"
        }
    }
}
```

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/KpUisfpzBmAPh2pKc/builds/C6w7ZBvjEszlaDegk/openapi.json
