Paycom Jobs API.
HR and payroll platform with integrated recruiting, onboarding, and talent management features.
Try the API.
Test Jobs, Feed, and Auto-Apply endpoints against https://connect.jobo.world with live request/response examples, then copy ready-to-use curl commands.
What's in every response.
Data fields, real-world applications, and the companies already running on Paycom.
- HCM integration
- Payroll data
- Onboarding
- Time tracking
- Compliance management
- Talent acquisition
- 01Enterprise job aggregation
- 02HR compliance monitoring
- 03Payroll-integrated recruiting
How to scrape Paycom.
Step-by-step guide to extracting jobs from Paycom-powered career pages—endpoints, authentication, and working code.
import re
career_url = "https://www.paycomonline.net/v4/ats/web.php/portal/A7EA16ADA834B1F889CBB30B17AEB9A9/career-page"
# Extract the 32-character hex portal key
match = re.search(r'portal/([A-F0-9]+)/career-page', career_url)
if match:
portal_key = match.group(1)
print(f"Portal Key: {portal_key}")import re
import requests
career_url = "https://www.paycomonline.net/v4/ats/web.php/portal/A7EA16ADA834B1F889CBB30B17AEB9A9/career-page"
# Fetch the career page HTML
response = requests.get(career_url)
html = response.text
# Extract JWT token from the embedded JavaScript
jwt_match = re.search(r'"(eyJ[A-Za-z0-9_-]+.[A-Za-z0-9_-]+.[A-Za-z0-9_-]+)"', html)
if jwt_match:
jwt_token = jwt_match.group(1)
print(f"JWT Token: {jwt_token[:50]}...")
else:
print("JWT token not found in page")import requests
jwt_token = "YOUR_JWT_TOKEN"
url = "https://portal-applicant-tracking.us-cent.paycomonline.net/api/ats/job-posting-previews/search"
headers = {
"authorization": jwt_token,
"content-type": "application/json",
"locale": "en-US",
"origin": "https://www.paycomonline.net",
"referer": "https://www.paycomonline.net/",
}
payload = {
"skip": 0,
"take": 100, # Fetch up to 100 jobs per request
"filtersForQuery": {
"distanceFrom": 0,
"workEnvironments": [],
"positionTypes": [],
"educationLevels": [],
"categories": [],
"travelTypes": [],
"shiftTypes": [],
"otherFilters": [],
"keywordSearchText": "",
"location": "",
"sortOption": ""
}
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
print(f"Total jobs: {data.get('jobPostingPreviewsCount', 0)}")
for job in data.get('jobPostingPreviews', []):
print(f" - [{job['jobId']}] {job['jobTitle']} ({job['locations']})")import requests
jwt_token = "YOUR_JWT_TOKEN"
job_id = 216798
portal_key = "A7EA16ADA834B1F889CBB30B17AEB9A9"
url = f"https://portal-applicant-tracking.us-cent.paycomonline.net/api/ats/job-postings/{job_id}"
headers = {
"authorization": jwt_token,
"content-type": "application/json",
"locale": "en-US",
"origin": "https://www.paycomonline.net",
"referer": "https://www.paycomonline.net/",
}
response = requests.get(url, headers=headers)
data = response.json()
job = data.get("jobPosting", {})
print({
"id": job.get("jobId"),
"title": job.get("jobTitle"),
"location": job.get("location"),
"position_type": job.get("positionType"),
"remote_type": job.get("remoteType"),
"salary_range": job.get("salaryRange"),
"is_hot_job": job.get("isHotJob"),
"apply_available": job.get("applyAvailable"),
"description_length": len(job.get("description", "")),
})
# Construct the job URL for reference
job_url = f"https://www.paycomonline.net/v4/ats/web.php/portal/{portal_key}/jobs/{job_id}"
print(f"Job URL: {job_url}")import requests
import time
jwt_token = "YOUR_JWT_TOKEN"
url = "https://portal-applicant-tracking.us-cent.paycomonline.net/api/ats/job-posting-previews/search"
headers = {
"authorization": jwt_token,
"content-type": "application/json",
"locale": "en-US",
"origin": "https://www.paycomonline.net",
"referer": "https://www.paycomonline.net/",
}
all_jobs = []
skip = 0
take = 100
while True:
payload = {
"skip": skip,
"take": take,
"filtersForQuery": {
"distanceFrom": 0,
"workEnvironments": [],
"positionTypes": [],
"educationLevels": [],
"categories": [],
"travelTypes": [],
"shiftTypes": [],
"otherFilters": [],
"keywordSearchText": "",
"location": "",
"sortOption": ""
}
}
response = requests.post(url, headers=headers, json=payload)
data = response.json()
jobs = data.get("jobPostingPreviews", [])
all_jobs.extend(jobs)
total_count = data.get("jobPostingPreviewsCount", 0)
print(f"Fetched {len(jobs)} jobs (total: {len(all_jobs)}/{total_count})")
if len(all_jobs) >= total_count or len(jobs) == 0:
break
skip += take
time.sleep(0.5) # Rate limiting delay
print(f"\nTotal jobs collected: {len(all_jobs)}")import re
import requests
def get_fresh_jwt_token(portal_key: str) -> str:
"""Fetch career page and extract a fresh JWT token."""
career_url = f"https://www.paycomonline.net/v4/ats/web.php/portal/{portal_key}/career-page"
response = requests.get(career_url, timeout=15)
response.raise_for_status()
jwt_match = re.search(r'"(eyJ[A-Za-z0-9_-]+.[A-Za-z0-9_-]+.[A-Za-z0-9_-]+)"', response.text)
if not jwt_match:
raise ValueError("JWT token not found in page")
return jwt_match.group(1)
def fetch_jobs_with_retry(portal_key: str, max_retries: int = 2) -> list:
"""Fetch jobs with automatic token refresh on 401 errors."""
jwt_token = get_fresh_jwt_token(portal_key)
url = "https://portal-applicant-tracking.us-cent.paycomonline.net/api/ats/job-posting-previews/search"
headers = {
"authorization": jwt_token,
"content-type": "application/json",
"locale": "en-US",
"origin": "https://www.paycomonline.net",
"referer": "https://www.paycomonline.net/",
}
for attempt in range(max_retries + 1):
response = requests.post(url, headers=headers, json={"skip": 0, "take": 100, "filtersForQuery": {}})
if response.status_code == 401:
print(f"Token expired, refreshing (attempt {attempt + 1})...")
jwt_token = get_fresh_jwt_token(portal_key)
headers["authorization"] = jwt_token
continue
response.raise_for_status()
return response.json().get("jobPostingPreviews", [])
raise Exception("Failed to fetch jobs after token refresh")
# Usage
portal_key = "A7EA16ADA834B1F889CBB30B17AEB9A9"
jobs = fetch_jobs_with_retry(portal_key)
print(f"Retrieved {len(jobs)} jobs")The token is embedded in the HTML and may change location. Ensure your regex pattern matches the full JWT format (eyJ...). If the page structure changes, inspect the HTML source to find the new token location.
JWT tokens expire after several hours. Re-fetch the career page and extract a fresh token. Always extract the token at the start of each scraping session.
Verify the 32-character hex key is correct. Keys may change if a company reconfigures their Paycom instance. Use search engines or the Wayback Machine to find current portal keys.
Add delays between API requests (0.5-1 second). Ensure the origin and referer headers are set correctly. For high-volume scraping, consider using residential proxies.
The listings API returns truncated descriptions. Always fetch full job details using the job-postings endpoint for complete description and qualifications fields.
Check the secondaryLocations array and the locations field which may contain multiple entries separated by semicolons. Parse these to get all location options.
- 1Extract a fresh JWT token at the start of each scraping session
- 2Use take=100 to minimize pagination requests for large job boards
- 3Include proper origin and referer headers in all API requests
- 4Fetch full job details separately as listings return truncated descriptions
- 5Handle HTML content in description and qualifications fields
- 6Implement token refresh logic for long-running scraping sessions
One endpoint. All Paycom jobs. No scraping, no sessions, no maintenance.
Get API accesscurl "https://enterprise.jobo.world/api/jobs?sources=paycom" \
-H "X-Api-Key: YOUR_KEY" Access Paycom
job data today.
One API call. Structured data. No scraping infrastructure to build or maintain — start with the free tier and scale as you grow.