# Workday Jobs Scraper | Descriptions & Salaries (`peerless_columbine/workday-public-jobs-data`) Actor

Scrape public Workday career sites for jobs, descriptions, locations and published salaries. Search keywords, filter posting dates and export JSON/CSV across multiple company boards.

- **URL**: https://apify.com/peerless\_columbine/workday-public-jobs-data.md
- **Developed by:** [tingyou333 zhuang](https://apify.com/peerless_columbine) (community)
- **Categories:** Jobs, Lead generation
- **Stats:** 2 total users, 1 monthly users, 100.0% runs succeeded, 0 bookmarks
- **User rating**: No ratings yet

## Pricing

from $0.06 / 1,000 delivered jobs

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?

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

## Workday Jobs Scraper | Descriptions & Salaries

Scrape public Workday career sites for jobs, descriptions, locations and published salaries. Search keywords, filter posting dates and export JSON/CSV across multiple company boards.

**Useful for:** Collect jobs from company career sites; filter newly posted roles; compare published salary ranges.

**Why choose this Actor:** Collect from multiple public Workday boards with job descriptions, exact posting-date filters and salary evidence. Saved results remain available if a later source request fails.

### Try a small sample

1. Click **Try for free**, then open **Input** and switch to JSON.
2. Paste the example below and click **Start**. It uses a small result limit.
3. Open the dataset to inspect results, then export JSON, CSV or Excel. Source restrictions can still cause partial or failed runs.

```json
{
  "startUrls": [
    {
      "url": "https://workday.wd5.myworkdayjobs.com/Workday"
    }
  ],
  "maxJobsPerSite": 5,
  "includeDetails": true
}
```

### Cost at a glance

Primary billing unit: **Delivered job**. Rates below are per **1,000** primary events.

| Free plan | Starter / Bronze | Scale / Silver | Business / Gold and higher |
|---:|---:|---:|---:|
| $0.08 | $0.08 | $0.072 | $0.064 |

Platform runtime usage is included. The Actor-start event is $0.0005 per GB of run memory, with a minimum of one event. Other event types, where enabled, are listed in the **Pricing** tab. “Try for free” uses available account credits; it does not make usage unlimited or unmetered.

**Coverage to know:** Use public career-site URLs, not internal HR portals. Salary fields depend on employer disclosures. Runtime is included in pricing; a platform Actor-start event also applies.

For Greenhouse, Lever, Ashby and other ATS jobs, see our [companion Actor](https://apify.com/peerless_columbine/multi-ats-jobs-scraper?utm_source=actor_readme\&utm_medium=referral\&utm_campaign=storefront_round23). It runs and bills separately.

### Guides and full reference

Collect jobs from public Workday career sites without personal login credentials. This is an independently developed tool, not affiliated with or endorsed by Workday. Prices include platform runtime usage.

### Inputs

`startUrls` accepts public career-site URLs using either `tenant.wdN.myworkdayjobs.com/[locale/]Site` or `wdN.myworkdaysite.com/[locale/]recruiting/tenant/Site`. Workday and Microchip sites have been cloud verified. Internal HR portals and application submission are not supported.

- `searchText`: source-native keyword search; default empty.
- `maxJobsPerSite`: hard output cap per site; default `0` collects all matching jobs.
- `includeDetails`: default `true`; fetch native job details.
- `descriptionFormat`: `both` (default), `html`, or `text`.
- `postedAfter`: inclusive `YYYY-MM-DD` cutoff. Requires details; with details disabled it is ignored with a warning for competitor compatibility. Missing exact dates cause failure rather than guessed filtering.
- `detailConcurrency`: 1–10, default 5.
- `errorOutputMode`: `report` (default) for a jobs-only dataset, or `dataset` to include unbilled source-error records alongside jobs.

Date filtering traverses the list until exhaustion or the output cap. A restrictive date filter may still require fetching every detail and incur resource costs despite few or zero returned jobs. No date-order early stop is assumed.

For API input, supply `startUrls` as URL objects, as shown above.

### Output and delivery

Native job IDs, company, locations, country, exact posted date, description and source URLs are retained when available. Missing source fields remain null. Country can fall back to the native location country. Salary extraction preserves explicit currencies and multiple labeled ranges; ambiguous dollar signs do not imply USD, and sales deal amounts are excluded. Apply URLs are derived from public job paths. Rendered application pages were verified for Workday and Microchip; this does not establish support for every regional variant.

Validated batches are saved to the default dataset during traversal. If a later source page fails, previously delivered rows remain available and other requested sites are attempted. The overall run fails when any site fails; consult `RUN_REPORT` and `RUN_ERROR` for the affected site and its delivered count. `SITE_SUMMARY` includes successful and source-failed sites in attempted order. Failed entries have `status: "failed"`, `traversalComplete: false`, confirmed `deliveredRows` and an `error` object. Available collection metadata is retained; unknown totals are omitted rather than reported as zero. Unattempted sites are counted separately in `RUN_REPORT.unprocessedSites`; uncertain storage failures still stop immediately. Successful entries retain source totals, facets and cap indicators. `DELIVERY_PROGRESS` records confirmed delivery counts. Its `complete` flag means processing finished without a recorded source failure or event-budget interruption; use each site's `traversalComplete` to distinguish a capped result from a full crawl.

An uncertain dataset write stops the run without application-level replay. Progress records do not implement restart/resume or an exactly-once guarantee. Some details fetched concurrently may exceed the requested output cap, although delivered results respect it.

### Verified scope and current limits

Real cloud checks cover Workday's 388-job feed, full details, Workday and Microchip URL families, multiple sites, date and description filters, empty search, output limits and continued delivery after a failed site. Job-result event counts were verified against delivered rows for normal, empty, budget-limited and mixed-error runs. These owner-account tests establish behavior, not customer revenue or universal employer coverage.

A subsequent NVIDIA cloud run completed 15 public category branches and returned 2,606 unique full-detail jobs, beyond the unfiltered API's 2,000-result window. All 2,606 native IDs were unique, dataset fields passed schema checks, and job-result events matched delivered jobs. The three independently checked older jobs missing from the unfiltered result were present. This verifies one source snapshot; it is not a guarantee of every employer or future source changes.

Mid-stream transport and uncertain-write failures are covered by local fault injection. No exactly-once recovery or automatic restart of a failed crawl is promised. The API export example resumes observation and download of an existing run; it does not restart collection.

### Result fields and integrations

| Group | Fields | Availability |
| --- | --- | --- |
| Identity | `resultType`, `title`, `tenant`, `siteId`, `sourceUrl`, `url`, `scrapedAt`, `totalJobsOnSite` | List and detail modes |
| Listing | `locationsText`, `postedOn`, `jobReqId`, `remoteType` | Source dependent; details can refine values |
| Detail identity | `workdayInternalId`, `jobPostingId`, `company`, `applyUrl` | Detail mode; company may be null |
| Location | `primaryLocation`, `additionalLocations`, `country`, `countryCode` | Detail mode; native values only |
| Dates and work | `postedDate`, `endDate`, `timeLeftToApply`, `timeType`, `canApply` | Detail mode; source dependent |
| Description | `descriptionHtml`, `descriptionText` | Selected by `descriptionFormat` |
| Salary | `salaryMin`, `salaryMax`, `salaryCurrency`, `salaryText`, `salaryRanges` | Detail mode; extraction from published description |

`salaryRanges` contains `{text, min, max, currency}` records. The source text matters: the same posting can contain several geographic pay bands. Missing fields in list mode are not a promise of null-filled detail fields. Native dates and relative listing dates are distinct.

The dataset supports JSON/CSV export through Apify. Jobs, Salary evidence, Source identity and Diagnostics table views have been inspected with real output in Console. Output links expose the dataset, run report, site summaries and delivery progress.

For API automation, submit the input object to `POST https://api.apify.com/v2/acts/peerless_columbine~workday-public-jobs-data/runs` with your own Apify token in the Authorization header. Poll the returned run ID, then use its `defaultDatasetId` and `defaultKeyValueStoreId` to retrieve data and reports. Use your own Apify account token and check the current Pricing tab before starting a run. Check run status and reports before treating a dataset as complete. A dedicated n8n node is implemented under integrations/n8n in the source. Its installed-runtime validation and remaining distribution limits are described below. MCP uses Apify's hosted service.

#### Dedicated n8n node — installation preview

The `n8n-nodes-workday-public-jobs` package provides Get Jobs, Start Run and Resume Run operations. It retains the competing node's `careersUrls`, `searchText`, `maxResults`, `includeDetails`, `descriptionFormat`, `postedAfter`, `output` and `fields` parameters. Defaults are 25 jobs per site, full details, text descriptions and simplified output. Changing node type and selecting your own credentials is required; this is not a drop-in replacement for a third-party package name.

Jobs appear on the first output; run IDs, terminal status and source/delivery reports appear on the second. Exports paginate in batches of 1,000. Failed or budget-limited runs are rejected unless you explicitly allow partial output, which retains `complete: false`. An expired local wait returns the existing run ID for Resume Run. Disable automatic retry on Start Run/Get Jobs to avoid creating another paid run after a lost response. For long jobs, connect Start Run's second output through your durable Wait/Resume workflow. Full source exhaustion is separate from successful capped processing; inspect `SITE_SUMMARY`.

Installed n8n 2.38.1 validation covers loading the package, encrypted API-token credentials, resuming an existing run, and a new one-job Start → Resume workflow. The same run ID passed between nodes, a full-detail job and completion reports were returned, and cloud events matched one job plus one start. Separately, the node execute method downloaded an existing 2,606-job dataset in three pages and retained explicit failure state for a partial three-job dataset.

In n8n AI Agent tool mode, version 0.1.1 returns `{jobs, run}` envelopes so status, limits and reports remain visible alongside jobs. Ordinary nodes retain their two outputs. This fixes version 0.1.0's loss of the second output when n8n converted the node into an AI tool. Actual AI Agent 3.1 workflows in n8n 2.38.1 verified both a successful one-job run and a failed three-job partial run: the agent received the correct run IDs and complete/incomplete flags. These tests used a deterministic local chat-model fixture that requests the tool and echoes its response; they validate integration, not external LLM reasoning. No test model is bundled with the product.

The package and an inactive example workflow are included in the Actor source under `integrations/n8n`; a local tarball has been produced. Version 0.1.2 was also checked in the actual n8n 2.38.1 editor: manual Resume execution returned one job and one successful report item. Resume hides controls that only apply to new runs, and the Docs button links to this README. Version 0.1.3 additionally passed OAuth browser consent and an existing-run export in isolated n8n 2.38.1, using only the OAuth credential. An initial connection-closed error was followed by a successful retry of the same read: one job and one report, with no new Actor start. The local client was registered dynamically with Apify and used full\_api\_access and PKCE. No client secret or user token is included in the package. Token refresh, production callbacks, public npm distribution and public customer access remain unverified. Do not attempt an npm registry install under this name until a published package is announced. API-token credentials must belong to the invoking user; no credential is bundled with the node.

#### AI clients through MCP

Connect a client supporting Streamable HTTP to Apify's hosted MCP service. The configuration below uses the client's OAuth flow; each customer authorizes their own Apify account. Clients without OAuth can use their own token in an Authorization header. See the [official MCP setup guide](https://docs.apify.com/integrations/mcp).

```json
{
  "mcpServers": {
    "workday-jobs": {
      "url": "https://mcp.apify.com/?tools=peerless_columbine/workday-public-jobs-data,get-actor-run,get-dataset-items,get-key-value-store-record&telemetry-enabled=false"
    }
  }
}
```

1. Load tools and select `peerless_columbine--workday-public-jobs-data` (client display names can differ).
2. Supply the Actor inputs, including an explicit `maxJobsPerSite` cap. For example, use the input below. `waitSecs` controls MCP waiting, not the Actor's execution deadline.
3. Save the returned `runId`. If the run is still active, call `get-actor-run` with that ID. A waiting timeout is not a reason to start a second paid run.
4. Retrieve jobs with `get-dataset-items`, using the returned default dataset ID. Paginate with `offset` and `limit`; a tool preview is not proof that all jobs have been retrieved.
5. Use `get-key-value-store-record` with the returned default key-value-store ID to read `RUN_REPORT`, `DELIVERY_PROGRESS` and `SITE_SUMMARY`. Check failures, budget stops and each site's `traversalComplete` before treating a capped dataset as a complete source crawl.

```json
{"startUrls":[{"url":"https://workday.wd5.myworkdayjobs.com/Workday"}],"maxJobsPerSite":1,"includeDetails":true,"descriptionFormat":"both","waitSecs":0}
```

Owner-account hosted MCP validation on September 9, 2026 completed tool discovery, asynchronous start, status polling, job retrieval and report retrieval: one full-detail job, one job-result event and one start event. The source listed 392 jobs; this deliberately capped test did not crawl all 392. It does not establish public customer access while the Actor remains private, client-specific OAuth UI acceptance, or x402 payment acceptance. No independent MCP server or separate MCP fee is bundled; normal Actor pricing applies. The hosted service may include auxiliary tools such as abort-run.

### Example result

Selected fields from a verified public job, shown as a dated example rather than a guarantee that the job is still open. Description and other fields are omitted here for readability.

```json
{
  "resultType": "job",
  "title": "BT Strategic Operations & Enablement - Senior Director",
  "company": "Workday, Inc.",
  "tenant": "workday",
  "siteId": "Workday",
  "jobReqId": "JR-0109093",
  "jobPostingId": "BT-Strategic-Operations---Enablement---Senior-Director_JR-0109093-1",
  "workdayInternalId": "d70e85d4b5881001589826cf95cf0000",
  "primaryLocation": "USA, CA, Pleasanton",
  "additionalLocations": [
    "USA, GA, Atlanta"
  ],
  "countryCode": "US",
  "postedDate": "2026-09-08",
  "salaryMin": 264700,
  "salaryMax": 397100,
  "salaryCurrency": "USD",
  "url": "https://workday.wd5.myworkdayjobs.com/Workday/job/USA-CA-Pleasanton/BT-Strategic-Operations---Enablement---Senior-Director_JR-0109093-1",
  "applyUrl": "https://workday.wd5.myworkdayjobs.com/Workday/job/USA-CA-Pleasanton/BT-Strategic-Operations---Enablement---Senior-Director_JR-0109093-1/apply"
}
```

### Pricing

| Event | Free / Bronze | Silver | Gold / Platinum / Diamond |
| --- | --- | --- | --- |
| 1,000 delivered jobs | $0.08 | $0.072 | $0.064 |
| Start, per allocated GB (minimum one) | $0.0005 | $0.0005 | $0.0005 |

Platform runtime resource usage is included. The automatic start fee also applies to empty and failed runs; filtered-out jobs and failed source requests have no job-result fee. At the default 128 MB allocation, the start event is charged once. Post-run storage/API access can incur standard Apify account costs. The Pricing tab shows the current configured rates.

Default run resources are 128 MB and 3,600 seconds. The 2,606-job NVIDIA run used 128 MB, concurrency 10 and a 1,800-second timeout, completing in about 728 seconds. The longer default timeout accommodates the default concurrency of 5 and larger sources; it is a time limit, not a fixed run duration. Larger sites or unusually large descriptions may need different run resources. Lower memory can take longer. Missing or failed pages produce an explicit failure, not a silently truncated success.

A site counted in `completedSites` has fulfilled the requested processing or output cap; this does not necessarily mean every source job was returned. Check `traversalComplete` for source exhaustion. If the output cap and spending limit are reached together, that site is complete for the requested cap while subsequent sites can remain unprocessed.

### Error-row integration mode

Set `errorOutputMode` to `dataset` when your integration expects source errors in the dataset. The default `report` keeps a jobs-only dataset. In dataset mode, records with `resultType: "error"` include the site identity, error type and message, a troubleshooting hint and the number of jobs delivered before that site failed. They do not incur a job-result event charge; the run start fee still applies. The whole run remains failed if any site fails, while successful site jobs remain available. Filter `resultType == "job"` in job-processing workflows.

`RUN_REPORT.deliveredRows` counts jobs; `errorRows` counts diagnostics and `totalDatasetRows` counts both. Dataset row count alone is therefore not the billable job count in this mode. Invalid top-level inputs are rejected before collection. This provides the documented error-row workflow, but exact competitor error object keys have not been verified against a paid competitor run.

#### Source records without a public job page

Some career sites include a requisition identifier in their list but omit both its title and public path. The Actor continues through later pages and delivers valid jobs. It reports these unavailable records with their source offsets in `RUN_ERROR.failures[].unavailableJobs`, and marks the run failed rather than claiming full data completeness. `collectionSummary.sourceTraversalComplete` describes pagination only; it does not mean that unavailable job details were obtained. Unavailable records incur no job-result event. With `errorOutputMode: "dataset"`, a diagnostic record is also saved without a job-result event.

Cross-page repeated jobs are not delivered or billed twice. The Actor continues later pages, records the repeated path and offset in the failure report, and marks the run incomplete: repeated listings can indicate that the live source changed while paging, so deduplicating alone cannot prove that no other job was missed. Source record diagnostics may contain either a requisition identifier or an external path, depending on what the public feed supplied.

For incomplete sources, `RUN_ERROR.failures[].collectionSummary` separates `unavailableRows` (no usable public job page), `duplicateRows` (repeated source positions), and `sourceIssueRows` (their sum). If a later source request fails, `sourceFailure` retains that cause alongside previously observed issues. `sourceTraversalComplete` reports whether all source pages were walked; `traversalComplete` remains false when distinct-job completeness cannot be established.

#### Python export and resume example

The Python client below uses only the standard library. Save it as `export_jobs.py`, and save the following input as `input.json`. The same files are included under `examples/` in the source, but access to the Actor source is not required. Set `APIFY_TOKEN` in your environment, then run:

```sh
python3 export_jobs.py --input input.json --out-dir workday-export
```

It saves the run ID immediately and exports the dataset in pages, including datasets larger than 1,000 records. To observe an existing run without creating or paying for another run:

```sh
python3 export_jobs.py --run-id YOUR_RUN_ID --out-dir workday-export
```

The client saves available results even when the run fails or exhausts its event budget, marks the exported report incomplete, and exits with code 2. If a submission response is lost, inspect Console before submitting again. This is an API example, not a custom n8n node. Event caps do not universally limit platform resource spending.

##### Save as `input.json`

```json
{
  "startUrls": [{"url": "https://workday.wd5.myworkdayjobs.com/Workday"}],
  "maxJobsPerSite": 20,
  "includeDetails": true,
  "descriptionFormat": "both",
  "errorOutputMode": "dataset"
}
```

##### Save as `export_jobs.py`

```python
#!/usr/bin/env python3
"""Standard-library API client; explicit resume and partial-result reporting."""
import argparse,json,os,time,sys
from pathlib import Path
from urllib.request import Request,urlopen
from urllib.error import HTTPError
from urllib.parse import urlencode,quote

BASE='https://api.apify.com/v2/'
TERMINAL={'SUCCEEDED','FAILED','ABORTED','TIMED-OUT'}

def request(path,token,body=None,missing_ok=False):
    data=json.dumps(body).encode() if body is not None else None
    req=Request(BASE+path,data=data,headers={'Authorization':'Bearer '+token,'Content-Type':'application/json'})
    try:
        with urlopen(req,timeout=60) as response:return json.load(response)
    except HTTPError as exc:
        if missing_ok and exc.code==404:return None
        raise RuntimeError(f'Apify HTTP {exc.code}; inspect account access and run status') from None
    except (OSError,ValueError):
        detail='Run submission outcome is uncertain; inspect Console before submitting again.' if body is not None else 'Read failed; resume with the saved run ID.'
        raise RuntimeError(detail) from None

def download_dataset(dataset_id,token,call=request):
    rows=[]
    while True:
        batch=call('datasets/'+quote(dataset_id,safe='')+'/items?'+urlencode({'format':'json','clean':'true','limit':1000,'offset':len(rows)}),token)
        if not isinstance(batch,list):raise RuntimeError('Expected dataset array')
        rows.extend(batch)
        if len(batch)<1000:return rows

def main(argv=None):
    parser=argparse.ArgumentParser(description=__doc__)
    source=parser.add_mutually_exclusive_group(required=True)
    source.add_argument('--input',type=Path,help='Actor input JSON file')
    source.add_argument('--run-id',help='Resume observing an existing run; does not create another run')
    parser.add_argument('--out-dir',type=Path,default=Path('workday-export'))
    parser.add_argument('--max-charge',type=float,default=.05,help='Per-run event spending cap in USD')
    args=parser.parse_args(argv)
    token=os.environ.get('APIFY_TOKEN')
    if not token:parser.error('Set APIFY_TOKEN in your environment; do not put it in the input JSON')
    if args.max_charge<=0:parser.error('--max-charge must be positive')
    args.out_dir.mkdir(parents=True,exist_ok=True);handle=args.out_dir/'run-id.txt'
    if args.input:
        if handle.exists():parser.error('This output directory already has a run ID. Resume with --run-id or choose another directory.')
        body=json.loads(args.input.read_text())
        result=request('acts/peerless_columbine~workday-public-jobs-data/runs?'+urlencode({'maxTotalChargeUsd':args.max_charge}),token,body)
        run_id=result['data']['id'];handle.write_text(run_id+'\n')
    else:
        run_id=args.run_id
        if handle.exists() and handle.read_text().strip()!=run_id:parser.error('Output directory belongs to a different run')
        handle.write_text(run_id+'\n')
    print('Run ID:',run_id,flush=True)
    while True:
        run=request('actor-runs/'+quote(run_id,safe=''),token)['data']
        if run['status'] in TERMINAL:break
        time.sleep(5)
    rows=download_dataset(run['defaultDatasetId'],token)
    report=request('key-value-stores/'+quote(run['defaultKeyValueStoreId'],safe='')+'/records/RUN_REPORT',token,missing_ok=True)
    incomplete=run['status']!='SUCCEEDED' or report is None or report.get('stoppedByBudget',False)
    (args.out_dir/'jobs-and-diagnostics.json').write_text(json.dumps(rows,ensure_ascii=False,indent=2))
    (args.out_dir/'report.json').write_text(json.dumps({'runId':run_id,'status':run['status'],'incomplete':incomplete,'recordCount':len(rows),'report':report},indent=2))
    print(f"{run['status']}: {len(rows)} records saved; incomplete={incomplete}")
    return 2 if incomplete else 0

if __name__=='__main__':
    try:sys.exit(main())
    except RuntimeError as exc:print(str(exc),file=sys.stderr);sys.exit(1)
```

#### Large boards and capped source totals

The public NVIDIA feed was verified to report `total=2000` and wrap offset2,000 back to its first page. Source-native category filters exposed older jobs absent from that unfiltered result. For large requests, the Actor snapshots public facet branches before fetching details, recursively adding another available facet when a branch remains capped. It then merges public paths and fetches each unique job once. A small output cap without a date filter keeps the direct path.

The original `totalJobsOnSite` remains the source's reported number for compatibility. `listedCandidates` is the merged candidate count. `partitionReport` records branch filters, counts, pages, cross-branch overlaps and missing requisition IDs. In this mode `sourcePositionsTraversed` counts positions processed in the merged candidate snapshot; `partitionReport.partitionSourcePositions` counts leaf-branch source positions, including overlaps. Neither is automatically a count of distinct complete jobs.

Changing branch counts, repeated pages within a branch, or a capped branch without another public facet cause explicit failure. Cross-branch overlap is expected and is deduplicated. Reported facet counts are never simply summed and advertised as distinct jobs. The partition implementation passed the 2,606-job NVIDIA cloud check described above; the earlier unfiltered 2,000-job run was incomplete. `listPages` counts merged-candidate processing pages in this mode; `partitionReport.sourceListPages` records actual source list requests.

# Actor input Schema

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

Required public Workday career-site URLs, supplied as objects with a url field. Supported URL families: tenant.wdN.myworkdayjobs.com/\[locale/]Site and wdN.myworkdaysite.com/\[locale/]recruiting/tenant/Site. Workday and Microchip sites have been cloud tested. Internal HR portals, login-required pages and application submission are unsupported.

## `searchText` (type: `string`):

Optional keyword query passed to the site's own job search (matches titles and descriptions the same way the search box on the careers page does). Leave empty to return every job.

## `maxJobsPerSite` (type: `integer`):

Hard cap on delivered jobs per career site. 0 means all jobs matching the filters. Concurrent detail fetching may read a few additional jobs. A restrictive date filter can still require reading the complete source feed even with a small output cap.

## `includeDetails` (type: `boolean`):

When true (default), the actor opens each job's detail record to add the full description, exact ISO posted and end dates, employment type, all locations, country, and apply URL. When false, only the fast list fields are returned (title, location text, relative posted date, requisition ID) at one request per 20 jobs.

## `descriptionFormat` (type: `string`):

Format of the job description fields when details are fetched: 'html' keeps the original rich text, 'text' returns clean plain text, 'both' (default) returns both fields.

## `postedAfter` (type: `string`):

Inclusive exact date filter (YYYY-MM-DD). With includeDetails=false this is ignored with a warning. With details enabled, missing exact dates cause explicit failure. The Actor traverses the source until exhaustion or the output cap; it does not assume jobs are ordered by date. Few or zero matching jobs can therefore still incur full traversal costs.

## `detailConcurrency` (type: `integer`):

How many job-detail requests run in parallel (1 to 10, default 5). The actor always paces list pages and backs off politely on rate limits; raise this only for very large sites.

## `errorOutputMode` (type: `string`):

Choose dataset for integrations that expect error rows alongside jobs. Source-site failures produce resultType=error records without job-result charges. The run still fails when a site fails. Malformed top-level inputs are rejected before collection. Exact competitor error-row field names remain unverified.

## Actor input object example

```json
{
  "startUrls": [
    {
      "url": "https://workday.wd5.myworkdayjobs.com/Workday"
    }
  ],
  "maxJobsPerSite": 50,
  "includeDetails": true,
  "descriptionFormat": "both",
  "detailConcurrency": 5,
  "errorOutputMode": "report"
}
```

# Actor output Schema

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

No description

## `report` (type: `string`):

No description

## `sites` (type: `string`):

No description

## `progress` (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 = {
    "startUrls": [
        {
            "url": "https://workday.wd5.myworkdayjobs.com/Workday"
        }
    ],
    "searchText": "",
    "maxJobsPerSite": 50
};

// Run the Actor and wait for it to finish
const run = await client.actor("peerless_columbine/workday-public-jobs-data").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://workday.wd5.myworkdayjobs.com/Workday" }],
    "searchText": "",
    "maxJobsPerSite": 50,
}

# Run the Actor and wait for it to finish
run = client.actor("peerless_columbine/workday-public-jobs-data").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://workday.wd5.myworkdayjobs.com/Workday"
    }
  ],
  "searchText": "",
  "maxJobsPerSite": 50
}' |
apify call peerless_columbine/workday-public-jobs-data --silent --output-dataset

```

## MCP server setup

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

```

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/abdrL65Dk0xWlhPh4/builds/8qUBYggSHOsbkTFJE/openapi.json
