Paylocity Jobs API
Read job postings from any Paylocity recruiting board as structured JSON. Paylocity is the HR and payroll platform behind the career pages of thousands of employers, and every employer's board lives at recruiting.paylocity.com under its own board GUID. Pass GUIDs, board URLs or company names and get every open role with its department, structured address, remote flag, employment type, full HTML description and the pay range where the employer sets one. Set newerThan to 25h on a daily schedule and each run returns only the postings published since the last one, filtered on the board's own timestamp before any detail page is fetched, so there is no seen-list to keep. Turn on discoverOnly to map who hires through Paylocity instead: boards found in public web archive snapshots, each checked live for its open-jobs count, locations and departments.
Input parameters
| PARAMETER | TYPE | REQ | DEFAULT | DESCRIPTION |
|---|---|---|---|---|
| companies | string[] | no | — | Paylocity boards to read, mixed freely: a board GUID, a full recruiting.paylocity.com board URL, or a company name, which is matched against the boards discovery finds. A GUID or URL is exact. |
| startUrls | object[] | no | — | The same board URLs in URL-list form, as {url} objects. Merged with companies. |
| discoverAll | boolean | no | false | Enumerate Paylocity boards from public web archive snapshots and scrape jobs from an even sample of maxCompanies of them. No input list needed. |
| discoverOnly | boolean | no | false | Return one company row per board instead of jobs: board GUID, URL, live open-jobs count, locations and departments. Works on the discovered set or on the boards listed in companies. |
| discoveryQuery | string | no | — | Case-insensitive text matched against the board slug and GUID, to scope a discovery run to boards whose name contains it. |
| crawlDepth | integer | no | 2 | How many monthly web archive snapshots to combine during discovery, 1 to 8. Higher finds more and older boards and takes longer. |
| titleKeywords | string[] | no | — | Keep only jobs whose title contains any of these, for example nurse or driver. Filters run before billing, so a filtered job costs nothing. |
| departments | string[] | no | — | Keep only jobs whose hiring department contains any of these. Many Paylocity employers leave the department blank, and those jobs are dropped when this is set. |
| locationKeywords | string[] | no | — | Keep only jobs whose location name, city, state or address contains any of these, for example Remote, Indiana or South Bend. |
| remoteOnly | boolean | no | false | Keep only jobs the board flags as remote. |
| employmentTypes | string[] | no | — | Keep only jobs whose employment type matches, for example FULL_TIME, PART_TIME, CONTRACTOR, TEMPORARY or INTERN. Checked after the detail fetch, still before billing. |
| newerThan | string | no | — | The change-detection cutoff: a window like 24h, 7d or 2w, or an ISO date or datetime. Compared against each posting's published date before the detail fetch, so a daily schedule with 25h returns only new postings. |
| cutoffField | enum | no | updated | posted or updated. Paylocity publishes one timestamp per job, so both compare against the published date; the field is kept for parity with the other job APIs. |
| includeDescriptionMarkdown | boolean | no | false | Add descriptionMarkdown, the posting converted to Markdown for AI agents. A paid add-on billed per row that carries it. |
| includeDescriptionText | boolean | no | false | Add descriptionText, the posting flattened to plain text. A paid add-on billed per row that carries it. |
| verifyLive | boolean | no | true | Discovery only: fetch each board to confirm it is live and read its job count, locations and departments. Off lists the discovered boards unverified, and unverified rows are free. |
| includeInactive | boolean | no | false | Discovery only: also return boards that no longer respond, with status dead. Dead rows are always free. |
| report | enum | no | none | none, markdown or html. Also writes a digest of every scraped job, grouped by company, to the key-value store under REPORT, capped at 5,000 rows. One flat charge, job runs only. |
| maxCompanies | integer | no | 25 | Cap on boards a discovery run processes, 1 to 2,000, sampled evenly across everything discovered. — drives your bill |
| maxJobsPerCompany | integer | no | 0 | Cap on job rows per board after filtering. 0 means no per-board cap. |
| maxJobs | integer | no | 100 | Hard ceiling on rows across the whole run, the main cost control. 0 means unlimited. In a discoverOnly run it also caps the company rows. — drives your bill |
| maxConcurrency | integer | no | 5 | Parallel job-detail requests and board checks, 1 to 10. |
| proxyConfiguration | object | no | — | Optional. The public boards answer direct connections, so leave it off unless your network needs a proxy. |
Output schema
| FIELD | TYPE | DESCRIPTION | NULLABLE |
|---|---|---|---|
| resultType | string | What this row is: job, company (a discovery row) or error (a free in-band error). | no |
| id | string | The board's public job id, the one in the detail and apply URLs. | yes |
| title | string | The posting title. | yes |
| companyName | string | The hiring company's name as the board publishes it. | yes |
| boardGuid | string | The company's Paylocity board GUID. The tenant key and the dedupe key for boards. | yes |
| boardUrl | string | The company's public recruiting board URL. | yes |
| url | string | The public URL of the posting detail page. | yes |
| applyUrl | string | The public application URL for the posting. | yes |
| department | string | The hiring department, when the employer publishes one. | yes |
| location | string | The posting's location name as the board shows it. | yes |
| address | object | The structured posting address: street, city, state, zip and county. | yes |
| isRemote | boolean | Whether the board flags the posting as remote. | yes |
| indeedRemoteType | integer | The board's Indeed remote-type code for the posting. | yes |
| employmentType | string | The employment type from the job detail record, for example FULL_TIME, when published. | yes |
| isInternal | boolean | Whether the posting is an internal-only role. | yes |
| datePublished | string | When the posting was published on the board (ISO 8601). The date newerThan compares against. | yes |
| datePosted | string | The datePosted from the job detail record (ISO 8601). | yes |
| salaryRaw | object | The board's own structured baseSalary block, passed through verbatim when present. | yes |
| salaryMin | number | Lower bound of the published pay range. | yes |
| salaryMax | number | Upper bound of the published pay range. | yes |
| salaryCurrency | string | The pay currency code, for example USD. | yes |
| salaryPeriod | string | The normalized pay period: hour, day, week, month or year. | yes |
| salaryUnit | string | The raw pay unit from the source, for example YEAR or HOUR. | yes |
| snippet | string | The short listing snippet the board shows before the full description. | yes |
| descriptionHtml | string | The full posting description as HTML. On every job row at no extra charge. | yes |
| descriptionMarkdown | string | The posting as Markdown. Present only when the Markdown add-on is on. | yes |
| descriptionText | string | The posting as plain text. Present only when the text add-on is on. | yes |
| source | string | Always paylocity, for merging with other ATS datasets. | yes |
| sourceType | string | Always ats. | yes |
| jobCount | integer | Company rows: live jobs on the board when it was checked. | yes |
| status | string | Company rows: live (serving jobs), empty (verified, zero jobs), dead (no longer responds) or unverified (not checked). | yes |
| locations | string[] | Company rows: the location names the board advertises. | yes |
| departments | string[] | Company rows: the department names the board advertises. | yes |
| slugSource | string | Company rows: input (a GUID, URL or name you supplied) or common-crawl (found by bulk discovery in the public web archive). | yes |
| discoveredAt | string | Company rows: when the board was discovered or checked (ISO 8601, UTC). | yes |
| errorMessage | string | Error rows: a sanitized, human-readable explanation. | yes |
| context | string | Error rows: the input that produced the error, such as a GUID, URL or company name. | yes |
| scrapedAt | string | When this job or error row was produced (ISO 8601, UTC). | yes |
Worked examples
{"companies": ["0062c37f-a34c-479c-978c-bd800d23f223"], "maxJobs": 50}
{"companies": ["0062c37f-a34c-479c-978c-bd800d23f223"], "newerThan": "25h", "maxJobs": 200}
{"discoverOnly": true, "maxCompanies": 100, "maxJobs": 100}
{"discoverAll": true, "maxCompanies": 50, "titleKeywords": ["nurse"], "maxJobs": 200}
{"companies": ["0062c37f-a34c-479c-978c-bd800d23f223"], "includeDescriptionMarkdown": true, "maxJobs": 25}
Code
Read one board in one call
curl -X POST "https://api.apify.com/v2/acts/johnvc~paylocity-jobs-api/run-sync-get-dataset-items" \
-H "Authorization: Bearer $APIFY_TOKEN" \
-H "Content-Type: application/json" \
-d '{"companies": ["0062c37f-a34c-479c-978c-bd800d23f223"], "newerThan": "7d", "maxJobs": 50}'
Python
from apify_client import ApifyClient
client = ApifyClient("APIFY_TOKEN")
run = client.actor("johnvc/paylocity-jobs-api").call(
run_input={"companies": ["0062c37f-a34c-479c-978c-bd800d23f223"], "newerThan": "7d", "maxJobs": 50}
)
for row in client.dataset(run.default_dataset_id).iterate_items():
if row.get("resultType") == "error":
print("error:", row.get("errorMessage"))
else:
print(row.get("title"), "|", row.get("location"), "|", row.get("salaryMin"), "-", row.get("salaryMax"), "|", row.get("url"))
MCP
claude mcp add --transport http paylocity-jobs \ "https://mcp.apify.com/?tools=actors,docs,johnvc/paylocity-jobs-api"
Sample job row (synthetic)
{
"resultType": "job",
"id": "4400001",
"title": "Registered Nurse - Day Shift",
"companyName": "Example Health Partners",
"boardGuid": "3f2a9c1e-0000-4000-8000-00000000abcd",
"boardUrl": "https://recruiting.paylocity.com/recruiting/jobs/All/3f2a9c1e-0000-4000-8000-00000000abcd/Example-Health-Partners",
"url": "https://recruiting.paylocity.com/Recruiting/Jobs/Details/4400001",
"applyUrl": "https://recruiting.paylocity.com/Recruiting/Jobs/Apply/4400001",
"department": "Nursing",
"location": "Example Health Springfield",
"address": {
"street": "100 Main St.",
"city": "Springfield",
"state": "IL",
"zip": "62701",
"county": null
},
"isRemote": false,
"employmentType": "FULL_TIME",
"datePublished": "2026-10-01T09:30:00-05:00",
"salaryMin": 72000,
"salaryMax": 84000,
"salaryCurrency": "USD",
"salaryPeriod": "year",
"descriptionHtml": "Example Health Partners is hiring a day-shift RN...
",
"source": "paylocity",
"sourceType": "ats",
"scrapedAt": "2026-10-02T14:00:00Z"
}
What people use it for
- A daily new-postings feed across Paylocity employers with zero state
- Mapping employers that hire through Paylocity as a sales or recruiting list
- Backfilling a job board straight from the source instead of a third-party index
- Pay-range disclosure and remote-share research
- Markdown job descriptions for AI recruiting agents over MCP
More sources for Hiring signals and talent intelligence, Lead sourcing and CRM enrichment, Grounding AI agents and MCP tools →