Nexus Tools / Data guides

Workday career sites as JSON: the /wday/cxs endpoint behind myworkdayjobs.com, tested on NVIDIA, Salesforce and Adobe, with a Python example and a free sample

How the public JSON behind Workday career sites works, how to build the URL from a careers link, the list and detail calls, the 20-per-page and 2,000-result traps we hit, why it is not a documented API and what that means, and when an Actor saves you the code.

Updated: November 2026. Everything below was tested live on 6 November 2026.

The short version

1. From a careers URL to the endpoint

Take the URL of the career site. Three parts matter: the tenant (first label of the host), the data-center number wdN (second label), and the site (first path segment, after an optional locale such as en-US):

https://nvidia.wd5.myworkdayjobs.com/en-US/NVIDIAExternalCareerSite
        ^tenant  ^wd5                  ^locale  ^site

list:    POST https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/jobs
detail:  GET  https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite{externalPath}

Tenants and sites we confirmed on 6 November 2026 (company-chosen names, so copy them from the real URL, do not guess):

CompanyTenant / data centerSiteJobs reported on the first page
NVIDIAnvidia.wd5NVIDIAExternalCareerSite2,000 (see section 3)
Salesforcesalesforce.wd12External_Career_Site1,554
Ciscocisco.wd5Cisco_Careers1,457
Adobeadobe.wd5external_experienced281

Workday itself (workday.wd5/Workday) also worked when read through the Actor. A wrong site name on a real tenant gave HTTP 404; a tenant host that does not exist gave HTTP 422. The same 422 came back for the two other big names we tried, Walmart and Dell, with the site names we guessed; we did not find out whether the sites or the request were wrong, so treat 422 as "not usable this way".

2. The calls, with curl

# list: 20 jobs per page; must send Content-Type: application/json
curl -s -X POST "https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/jobs" \
  -H "Content-Type: application/json" \
  -d '{"appliedFacets":{},"limit":20,"offset":0,"searchText":""}'

# full text search: searchText
curl -s -X POST "https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/jobs" \
  -H "Content-Type: application/json" \
  -d '{"appliedFacets":{},"limit":20,"offset":0,"searchText":"data scientist"}'

# one job: the externalPath taken from the list
curl -s "https://nvidia.wd5.myworkdayjobs.com/wday/cxs/nvidia/NVIDIAExternalCareerSite/job/US-CA-Remote/Senior-Account-Manager--Hyperscale-and-AI-Native_JR2023413-1"

What the list returns

{
  "total": 2000,
  "jobPostings": [
    {
      "title": "Senior Account Manager, Hyperscale and AI Native",
      "externalPath": "/job/US-CA-Remote/Senior-Account-Manager--Hyperscale-and-AI-Native_JR2023413-1",
      "locationsText": "US, CA, Remote",
      "postedOn": "Posted Today",
      "bulletFields": ["JR2023413"]
    }, ...
  ],
  "facets": [ {"facetParameter": "jobFamilyGroup", "descriptor": "Job Category", "values": [...]}, ... ],
  "userAuthenticated": false
}

What the detail returns

The detail is {"jobPostingInfo": {...}, "hiringOrganization": {...}, "similarJobs": [...]}. In jobPostingInfo we found, among others: title, jobDescription (HTML), location, additionalLocations[], startDate (a date such as 2026-11-06: the real posting date), timeType ("Full time"), jobReqId, country.descriptor, jobRequisitionLocation.country.alpha2Code, externalUrl (the public job page) and, on some tenants, remoteType (Cisco returned "Onsite Only" for one job it listed). There is no salary field; if a company publishes pay it is inside the description text. There is no department field either.

3. Limits and traps (measured)

4. DIY: one Workday site to CSV in Python

This script parses a careers URL, searches for a phrase, pages through the list, fetches each job's detail and writes workday_jobs.csv. Run on 6 November 2026 with searchText "data scientist" on NVIDIA it reported total 98 and wrote 40 rows (the script's max_jobs limit). It needs pip install requests. Put a real contact in the User-Agent.

import csv
import re
import time
from urllib.parse import urlparse

import requests

HEADERS = {"User-Agent": "my-script/1.0 (contact: you@example.com)"}
CAREERS_URL = "https://nvidia.wd5.myworkdayjobs.com/NVIDIAExternalCareerSite"


def parse(url):
    """https://<tenant>.<wdN>.myworkdayjobs.com/[locale/]<site>/... -> (host, tenant, site)"""
    u = urlparse(url)
    m = re.match(r"^([a-z0-9-]+)\.wd\d+\.myworkdayjobs\.com$", u.hostname or "")
    parts = [p for p in u.path.split("/") if p]
    if parts and re.match(r"^[a-z]{2}-[A-Z]{2}$", parts[0]):      # optional locale, e.g. en-US
        parts = parts[1:]
    if not m or not parts:
        raise ValueError("not a myworkdayjobs.com career site URL")
    return u.hostname, m.group(1), parts[0]


def search(base, text="", max_jobs=40):
    """Yield list entries; the server accepts limit <= 20 and returns `total` on the first page only."""
    offset = 0
    while offset < max_jobs:
        r = requests.post(f"{base}/jobs", headers=HEADERS, timeout=60,
                          json={"appliedFacets": {}, "limit": 20, "offset": offset, "searchText": text})
        r.raise_for_status()
        data = r.json()
        if offset == 0:
            print("total reported:", data["total"])
        postings = data.get("jobPostings") or []
        yield from postings
        if len(postings) < 20:
            break
        offset += 20
        time.sleep(0.3)


def detail(base, external_path):
    r = requests.get(base + external_path, headers=HEADERS, timeout=60)
    r.raise_for_status()
    return r.json()["jobPostingInfo"]


host, tenant, site = parse(CAREERS_URL)
base = f"https://{host}/wday/cxs/{tenant}/{site}"
rows = []
for p in search(base, text="data scientist", max_jobs=40):
    d = detail(base, p["externalPath"])
    rows.append({"id": d["jobReqId"], "title": d["title"], "location": d.get("location"),
                 "country": (d.get("country") or {}).get("descriptor"),
                 "time_type": d.get("timeType"), "start_date": d.get("startDate"),
                 "url": d["externalUrl"]})
    time.sleep(0.3)

with open("workday_jobs.csv", "w", newline="", encoding="utf-8-sig") as f:
    w = csv.DictWriter(f, fieldnames=list(rows[0]))
    w.writeheader()
    w.writerows(rows)
print(len(rows), "jobs written")

It does not split by facets, so on a site with more than 2,000 jobs run it per facet or per search term, and it does not retry on errors. If a tenant answers 422, stop: the endpoint is not usable there.

Remember what you are using: an undocumented endpoint of someone else's product, used by their own career site. Keep volumes small, identify yourself, and expect to fix the script when Workday changes it. The postings are the employers' content: do not use them to contact individuals.

5. When the Actor saves time

For one site and a one-off export, the script above is free and enough. The Apify Actor Workday Jobs Scraper (by Nexus Scrapers) does the same calls with the housekeeping built in, and the multi-system Career Site Jobs Scraper adds Greenhouse, Lever, Ashby, Workable, Recruitee and Personio in the same schema (see the Greenhouse, Lever and Ashby guide).

Pricing is pay per result; the Actor page shows the current price.

Limits, from the code and our own run: it reads at most the first 1,000 listings of each site, so it will not walk a 2,000-job list to the end (use keywords or several runs). With includeDescription off there is no detail call and postedAt is approximate, derived from the "Posted N days ago" label (extras.postedAtApprox says so). Salary is always empty for Workday, because the endpoint has none. A remoteType value such as Cisco's "Onsite Only" was not mapped in our sample (workplaceType and isRemote are null for those jobs). It relies on an undocumented endpoint, so it can break the day Workday changes it.

6. Real sample: 20 normalized jobs

These 20 jobs were produced on 6 November 2026 by running the Actor's own code locally on the live endpoints (no Apify platform involved): the first postings of five public Workday sites, NVIDIA 5, Salesforce 4, Adobe 4, Cisco 4 and Workday 3, in the list's order (roughly newest first), not hand-picked. postedAt is the date-only startDate of each job. Description text is cut at 1,500 characters and the HTML description is left out to keep the files small. A scrub pass for e-mail addresses ran over every text field and none remain in the files.

Download: sample.json (full records, UTF-8) and sample.csv (flattened, lists joined with | , opens in Excel).

CompanyTitleLocationReq. idRemotePosted
NvidiaSenior Account Manager, Hyperscale and AI NativeUS, CA, RemoteJR2023413yes2026-11-06
NvidiaIndustry Development Specialist, AI NativesUS, CA, Santa ClaraJR2028623-2026-11-06
NvidiaIndustry Development Specialist, NCPUS, CA, Santa ClaraJR2023422-2026-11-06
NvidiaSystem Application EngineerTaiwan, TaipeiJR2029384-2026-11-06
NvidiaSenior System Software Engineer - GPU ServerTaiwan, TaipeiJR2029291-2026-11-06
SalesforceRecruiting Coordinator (Contract)Canada - TorontoJR367536-2026-11-06
SalesforceSoftware Engineering AMTSIndia - HyderabadJR356580-2026-11-06
SalesforceProduct Accessibility EngineerIndia - BangaloreJR367595-2026-11-06
SalesforceRegional Vice President, Sales EnterpriseSouth Africa - JohannesburgJR367434-2026-11-06
AdobeDirector Cybersecurity and Fraud Public PolicyWashington D.C.R173038-2026-11-06
AdobeRegional Security and Safety Manager for Wester…ParisR173261-2026-11-05
AdobeSenior Manager, Labor Relations EMEA (Location:…LondonR173441-2026-11-05
AdobeGroup Manager, Global Customer Operations & Gro…NoidaR171692-2026-11-05
CiscoEmbedded Software EngineerSan Jose, California, US2029178-2026-11-05
CiscoSenior FPGA EngineerSan Jose, California, US2027589-2026-11-05
CiscoLead Performance & AI Tools Engineer, HybridMilpitas, California, US2030105no2026-11-05
CiscoProduct Designer - Collaboration Devices & Work…Lysaker, Norway2028374no2026-11-05
WorkdayIncident ManagerNew Zealand, AucklandJR-0111310-2026-11-06
WorkdayPrincipal, Product Manager - Financial Reportin…USA, CA, PleasantonJR-0110096-2026-11-05
WorkdaySr Solution ArchitectUSA, CA, PleasantonJR-0111082-2026-11-05

"Remote" is the normalized isRemote: yes, no, or - when the site does not say. Note that sourceUrl in the records is the /wday/cxs/ detail URL and jobUrl the public page.

7. Terms

There is no public API documentation or developer terms for this endpoint to cite; it is the interface of the employers' career sites. That is why we keep volumes small, honor robots.txt and say plainly that it is unsupported. The postings belong to the employers; read the terms that apply to your use. This is not legal advice.

Links