spb/company-atlas
Public
Python 66.3%
TypeScript 22.7%
JavaScript 8.6%
HTML 1.4%
CSS 0.7%
1"""Workday public career sites — the JSON search endpoint the site's own frontend calls (spec §13 mode C, provenance stored):2`POST https://{tenant}.{wdN}.myworkdayjobs.com/wday/cxs/{tenant}/{site}/jobs` body {"appliedFacets":{},"limit":20,"offset":N,"searchText":""}3→ {total, jobPostings:[{title, externalPath, locationsText, postedOn, bulletFields:[reqId]}]}. Paginated by offset, bounded to4`MAX_JOBS_WD` postings. Verified 2026-09-12 against nvidia.wd5 / NVIDIAExternalCareerSite (fixture = first page)."""5from __future__ import annotations67import re8from collections.abc import Mapping9from typing import Any1011from companyatlas.connectors._ats_base import AtsConnector12from companyatlas.connectors._util import load_json, merged_result13from companyatlas.fetch import Fetcher, FetchResult14from companyatlas.sdk.connector import ConnectorContext, ConnectorMeta, register15from companyatlas.sdk.models import ExtractedJob16from companyatlas.taxonomy import FetchMode, Surface1718PAGE_LIMIT = 2019MAX_JOBS_WD = 40020API_RE = re.compile(r"https?://([a-z0-9-]+)\.(wd\d+)\.myworkdayjobs\.com/wday/cxs/([a-z0-9-]+)/([A-Za-z0-9_-]+)/jobs", re.IGNORECASE)21REQ_RE = re.compile(r"_([A-Z]{1,4}[-_]?\d{3,}[A-Z0-9-]*)$")222324@register25class WorkdayConnector(AtsConnector):26 vendor = "workday"27 meta = ConnectorMeta(connector_id="workday-v1", name="Workday career site (public JSON)", version="1", category=Surface.JOBS_BOARD,28 fetch_mode=FetchMode.JSON, default_interval_s=12 * 3600, url_pattern=r"myworkdayjobs\.com/wday/cxs/", pattern_required=True, priority=50,29 accept="application/json", description="Public Workday CXS job search endpoint (POST, paginated)")3031 def token(self, sensor: Mapping[str, Any]) -> str | None:32 m = API_RE.search(str(sensor.get("url") or ""))33 return f"{m.group(1)}/{m.group(4)}" if m else None3435 async def fetch(self, ctx: ConnectorContext, sensor: Mapping[str, Any], fetcher: Fetcher) -> FetchResult:36 url = str(sensor["url"])37 postings: list[dict[str, Any]] = []38 first: FetchResult | None = None39 total = 040 offset = 041 pages = 042 while True:43 body = {"appliedFacets": {}, "limit": PAGE_LIMIT, "offset": offset, "searchText": ""}44 res = await fetcher.post_json(url, body, headers={"Content-Type": "application/json"})45 pages += 146 data = load_json(res)47 if first is None:48 first = res49 total = int(data.get("total") or 0) if isinstance(data, dict) else 050 page = (data.get("jobPostings") if isinstance(data, dict) else None) or []51 postings.extend(p for p in page if isinstance(p, dict))52 offset += len(page)53 if not page or offset >= total or offset >= MAX_JOBS_WD:54 break55 assert first is not None56 return merged_result(first, {"total": total, "jobPostings": postings, "truncated": total > len(postings)}, pages=pages)5758 def parse_jobs(self, data: Any, sensor: Mapping[str, Any]) -> list[ExtractedJob]:59 m = API_RE.search(str(sensor.get("url") or ""))60 base = f"https://{m.group(1)}.{m.group(2)}.myworkdayjobs.com/{m.group(4)}" if m else ""61 out: list[ExtractedJob] = []62 for j in (data.get("jobPostings") if isinstance(data, dict) else []) or []:63 if not isinstance(j, dict) or not j.get("title"):64 continue65 path = str(j.get("externalPath") or "")66 bullets = [b for b in (j.get("bulletFields") or []) if isinstance(b, str)]67 req = bullets[0] if bullets else None68 if not req:69 mm = REQ_RE.search(path)70 req = mm.group(1) if mm else None71 out.append(ExtractedJob(title=str(j["title"]), url=(base + path) if base and path else None, external_id=req or path or None,72 location_text=j.get("locationsText") or None, raw={"postedOn": j.get("postedOn"), "bulletFields": bullets[:3]}))73 return out74