All platforms

Paylocity Jobs API

Query jobs from Paylocity boards through one API with ?source=paylocity — plus how Paylocity's recruiting board really behaves.

?source=paylocitysource reference

Paylocity is a payroll and HR platform with recruiting bolted on, sold to US small and mid-sized businesses. Its boards live at recruiting.paylocity.com/recruiting/jobs/All/<guid>, and they are the ones churches, clinics, school districts and regional operators actually post to. There are 4,782 Paylocity postings in this dataset — a number that moves hourly, so read it from /v1/meta rather than trusting this sentence.

This is the platform in our small-business set with the most honest caveat attached, and the caveat is the interesting part.

Try it#

BASH
curl -G https://api.hyperjobs.io/v1/jobs \
  -H "Authorization: Bearer $HYPERJOBS_KEY" \
  --data-urlencode "source=paylocity" \
  --data-urlencode "time_frame=7d" \
  --data-urlencode "limit=2"
Illustrative — the shape, not a live response
{
  "data": [
    {
      "id": "paylocity:1849327",
      "title": "Parish Office Coordinator",
      "company": {
        "slug": "001ed382-3060-4f7b-a324-d44d173bb6c8",
        "name": "St Catherine of Siena Church",
        "domain": "stcatherinekc.org",
        "website": "https://stcatherinekc.org",
        "logo": "https://media.licdn.com/dms/image/…",
        "industry": "Religious Institutions",
        "employee_count": 31
      },
      "location": {
        "remote": false,
        "countries": ["United States"],
        "cities": ["Kansas City"],
        "regions": ["MO"],
        "raw": ["Kansas City, MO, United States"]
      },
      "employment_type": ["FULL_TIME"],
      "work_arrangement": null,
      "seniority": null,
      "salary": null,
      "skills": ["administration", "scheduling"],
      "taxonomies": ["Administrative"],
      "apply_url": "https://recruiting.paylocity.com/Recruiting/Jobs/Details/1849327",
      "url": "https://recruiting.paylocity.com/Recruiting/Jobs/Details/1849327",
      "source": "paylocity",
      "posted_at": "2026-07-08T15:41:00.000Z",
      "expires_at": null,
      "updated_at": "2026-07-14T10:22:18.000Z"
    }
  ],
  "total": 2,
  "limit": 2,
  "offset": 0
}

How Paylocity boards actually work#

The board server-renders its whole list into a global, and the body needs a second call:

BASH
# 1. List — the board HTML carries `window.pageData` with every posting in it
curl -L "https://recruiting.paylocity.com/recruiting/jobs/All/<guid>"
 
# 2. Detail — schema.org JobPosting JSON-LD
curl -L "https://recruiting.paylocity.com/Recruiting/Jobs/Details/<JobId>"

window.pageData is genuinely good: a Jobs array with JobTitle, a full structured JobLocation, IsRemote, HiringDepartment and a PublishedDate that carries a real offset. What it does not carry is the description — Description is always "" on the list — so the body is one detail call per posting, and that is where this platform gets difficult.

Ignore the documented feed API#

`/recruiting/api/feed/jobs/{guid}` returns HTTP 500

Paylocity advertises a feed endpoint as its integration route. Called with a board GUID it returns 500 — verified on three tenants.

It isn't broken. The feed key is a separate per-tenant opt-in credential, not the GUID sitting in the board URL. So the official-looking endpoint is a dead end for public boards, and anyone who "fixes" a working scraper by switching to the documented API gets 500s for their trouble.

window.pageData is the real route.

The burst-429 is the whole story#

The detail endpoint throttles on a burst budget, not a rate. Roughly 12 or 13 requests get through and the rest 429 — measured identically at concurrency 4, 3 and 2. Turning the pool down does not fix it, because it isn't a concurrency problem. The budget refills within seconds.

Here's why that matters more than a normal rate limit: a 429 on the detail page means no JSON-LD, which means a description-less row that still counts as a successful scrape. Nothing errors. The board reports success. The jobs are hollow.

ApproachDescriptions
Fetch details with no 429 handling14%
Backoff and retry, 1s → 16s93%

The residual 7% on that measured board is real and not fixable: those postings have no JSON-LD and no description div, because the employer left the body blank.

What that means for the rows we serve

Across all 4,782 Paylocity rows in the dataset today, 76.5% carry a description — not the 93% a clean single-board run achieves.

The gap is the same throttle, met at rotation scale rather than on one board with room to breathe. We'd rather print the number that describes the rows you will actually get than the one from the best run. It's among the lowest description fills of anything we serve, and it is the honest state of this platform today. Check /v1/meta and coverage for where it currently sits.

What bites you#

LocationName is a venue, not a place. It reads "St Gabriel Catholic Church Kansas City" — a building's name, which no geocoder will do anything sensible with. The structured City / State / Country on JobLocation is the ground truth. Take the label instead and you geocode a parish hall.

The board token is a bare GUID, and so is the company name. Every Paylocity board is identified by a UUID, which means the fallback company name minted from the token is a UUID too. The detail page's hiringOrganization.name is the only human-readable employer this platform ever emits — so the description fetch that the 429 eats is also the identity fetch. Lose one, lose both.

There's no tier-1 company-domain route. Paylocity publishes nothing that resolves a board to a company domain, so identity has to be inferred from outside the source and does not always land. A related trap: the JS-shell notice on some board pages points at enable-javascript.com, which an unguarded domain-grabber will cheerfully record as the employer's website.

A bare UUID looks like something else's id. A guard that treats bare UUIDs as junk silently dropped every ADP and Paylocity board at once. Here the UUID is the real board id.

Or use ours#

Two calls per posting against a burst throttle that no concurrency setting avoids, across 2,653 GUID-named boards, where the fetch you need for the body is also the fetch you need for the employer's name.

You get the backoff already paid for, the structured address preferred over the venue label, PublishedDate carried through with its offset, the employer's name lifted out of the detail JSON-LD instead of a UUID, Paylocity rows deduplicated against the same job on LinkedIn or elsewhere, expiry by board diffing, and whatever company identity can be resolved for a platform that publishes none. And you get told, in the note above, exactly how complete the descriptions are rather than finding out later.

Query it with ?source=paylocity. Quickstart, then pricing.

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

Get an API key