Dev.to WebDev 🛠 Dev 👁 0 📖 3 min read

Workday says the board has 2,000 jobs. Target has 12,525. Reading the rest.

Ask a Workday career site for its jobs and the first answer states a total: r = requests.post( "https://target.wd5.myworkdayjobs.com/wday/cxs/target/targetcareers/jobs", json={"appliedFacets": {}, "limit": 20,

Ask a Workday career site for its jobs and the first answer states a total:

r = requests.post(
    "https://target.wd5.myworkdayjobs.com/wday/cxs/target/targetcareers/jobs",
    json={"appliedFacets": {}, "limit": 20, "offset": 0, "searchText": ""},
)
r.json()["total"]      # 2000

Target does not have 2,000 open jobs. It has 12,525. The number is the most
that search will return, and once you have paged to it the API just re-serves
page one: offsets past the ceiling come back as the first twenty postings
again, forever, which is how a paging loop that stops on "empty page" turns
into an infinite one.

Measured on 2026-09-22 across 3,916 Workday boards: 59 of them sit at exactly
that wall (a board shows 1,990-2,000 because postings of one requisition merge
into one job). Among them Target, Walmart, NVIDIA, Accenture, Citi, Airbus,
T-Mobile, PNC, Abbott, Kohl's, Sysco, Circle K and Trinity Health.

The counts are in the same answer you already have

The response carries a facets list, and those counts are of the whole board,
not of the 2,000:

Location_Country                 United States of America  12,452   India  73
Location_Region_State_Province   California 1,701   Texas 879   Florida 803 ...
jobFamilyGroup                   Stores 12,023   Internships 132 ...
workerSubType                    Regular 11,538   Seasonal 854   Intern 133
timeType                         Variable 11,427   Full time 1,098

Four of those sum to exactly 12,525. That agreement is the useful part: a
facet a posting carries once sums to the board, a facet it can carry several
times (skills, locations) sums higher, and one only some postings carry sums
lower. So the board's real size is the sum the most facets agree on.

Each facet value is its own search, with its own ceiling

appliedFacets narrows the search, and the narrowed search gets a fresh
2,000:

body = {"appliedFacets": {"Location_Region_State_Province": ["<value id>"]},
        "limit": 20, "offset": 0, "searchText": ""}

California is 1,701 postings, and 1,701 come back. So the board is read slice
by slice and the slices are joined on each posting's externalPath, which is
the posting's own address and therefore the one key that cannot collide:

  1. Read the first page. If total is exactly 2,000, take the facets.
  2. Work out the real size (the sum the most facets agree on).
  3. Pick the facet that covers that size and whose every value is under the ceiling, fewest values first. Target: its 52 states.
  4. Where one value is still over the ceiling, apply it and split again by a second facet. Petco needs this: 2,980 of its jobs are "Retail (Stores)", and inside that slice the schedule splits it 1,893 / 1,024.
  5. Where no facet covers the slice at all, use the best partial one AND read the slice's own 2,000: Petco's schedule field is blank on 63 postings, and those come back in the plain read.

What it returns

Read whole, on 2026-09-22:

Target      12,499 of 12,536   655 requests
Michaels     5,071 of  5,071   279
Petco        3,774 of  3,798   298
Home Depot  (Workday corporate site, 1,031, no ceiling)

Walmart went from 1,990 rows to 21,202, Circle K from 2,000 to 11,397.

Two things worth keeping when you build this:

A failed slice falls back to the plain 2,000. Target is ~650 requests
against ~100, so a transient error is six times likelier; a caller who got
2,000 rows yesterday should not get an exception today for the sake of the
other 10,499.

Nothing splits under the ceiling. If the caller wants 1,000 rows, the
plain search already answers, and the split is pure cost.

The other thing in that answer

While measuring this I found that bulletFields[0], which most code (mine
included) uses as the job id, is not an id on 224 of those boards: Thales
prints "Regular Employee" there, Michaels the state, Cracker Barrel the
store's street address. Anything that de-duplicates on it collapses the board:
61,107 jobs became 16,314, and a run for Thales returned 7 rows for 200 jobs.
The requisition is in the posting's address instead
(/job/<place>/<Title-Slug>_<req>), and the bullet is only safe when it IS
that requisition.

If you want the rows rather than the code, this is what
workday-jobs-scraper
does: a company name in, every open posting out, past the ceiling, as JSON.

📰 Read the original article on Dev.to WebDev

Originally published by Dev.to WebDev. Aggregated on AIWithGhost for educational purposes — full credit and traffic to the original publisher.