All platforms

Microsoft Jobs API

Query Microsoft's postings through one API with ?source=microsoft — plus the list field that swears every job is on-site, and a page size hard-capped at ten.

?source=microsoftsource reference

Microsoft is not a platform. It's one employer with a bespoke careers site, and this adapter reaches Microsoft and nothing else. Write Workday once and you reach every Workday tenant; write this one and you reach Microsoft. company is ignored — there is one.

Its jobs are worth having, and the only way to have them is a dedicated adapter maintained forever. We run it: query it with ?source=microsoft. /v1/meta is the authoritative live vocabulary, with the current count per source.

How Microsoft Careers actually works#

Microsoft moved to a platform it calls pcsx (apply.careers.microsoft.com); the old gcsservices API is dead. It's the same Eightfold-family platform our Eightfold adapter already reads — same workLocationOption enum. No browser, no auth: a plain browser User-Agent gets a 200.

GET /api/pcsx/search?domain=microsoft.com&query=&start=N&num=10          → positions[], count
GET /api/pcsx/position_details?position_id=<id>&domain=microsoft.com     → full HTML body

The list is structured but ships no description, so the detail call is an N+1 you can't skip — run only for the day's new reqs. Page 0 carries count (~1,600 jobs); the rest fan out in parallel.

`num` is capped at ten, server-side

Ask for num=100 and you get ten. The page size is fixed at ten no matter what you send, so a ~1,600-job board is ~160 list pages, then ~1,600 detail fetches on a cold run. Paginate sequentially and you blow the time budget; the adapter fans the pages out concurrently instead.

The list swears every job is on-site#

workLocationOption on the list record reads "onsite" for every job — measured 10 out of 10, including fully-remote roles with zero days in office. It is a broken field. The real arrangement lives on the detail payload, in efcustomTextWorkSite"0 days / week in-office – remote", "3 days / week in-office", "Fully on-site" — which the adapter parses into Remote / Hybrid / On-site, falling back to the broken list field only when the detail is missing.

Take workLocationOption at face value and you'd label a remote-first employer 100% on-site, with a well-formed field and nothing to alert you.

What bites you#

A 403 here is transient, not a ban

The pcsx edge is Akamai, and it's reputation-gated. From a clean IP a plain request 200s and the whole board scrapes. Hammer it — a handful of full-board runs inside fifteen minutes — and it trips a temporary IP-wide block that 403s even curl, then decays on its own. So a 403 is a momentary soft-block, not a wall: it's retried, and a persistently-blocked run fails safe (returns nothing, expires nothing) rather than wrongly shrinking the board.

Locations come two ways, and one is backwards. standardizedLocations is city-first ("Redmond, WA, US") — the shape a parser wants; locations is country-first ("United States, Washington, Redmond"). The adapter prefers the former and only falls back to the latter.

The cold start is the expensive one. ~1,600 detail fetches behind a ten-per-page list is real work; warm re-scrapes detail only the day's new reqs, and a detail that fails leaves the job with its structured list fields rather than dropping it.

Or use ours#

A ten-capped page size fanned out, a mandatory detail N+1 for descriptions, a work-arrangement field that lies on the list and has to be recovered from the detail, and an Akamai soft-block handled as transient — with Microsoft's rows in the same Job shape as every other source, dedup against the same role on LinkedIn, and the adapter's upkeep being ours instead of yours. Same deal as Amazon, Apple, Uber, TikTok, Google and IBM.

Sources · Quickstart

Every source above normalises onto the same schema, with the hiring company already joined onto each posting.

Get an API key