Jobvite Jobs API: Get Jobvite Job Listings from JSON-LD
TL;DR
Jobvite has no public JSON jobs API. Its hosted career page at jobs.jobvite.com lists every open job's link on one HTML page, with no pagination, and each job page carries a schema.org JobPosting JSON-LD block with the title, description, date, locations and sometimes salary. The listing has no dates, so you can only filter by age after fetching job pages. Watch for empty baseSalary placeholders, full country names, and old dates on evergreen postings.
On this page
Jobvite has no public JSON jobs API, so to get a company's Jobvite jobs, fetch https://jobs.jobvite.com/{company}/jobs to collect the job links, then read the schema.org JobPosting JSON-LD on each https://jobs.jobvite.com/{company}/job/{id} page. Neither request needs a key, and one listing page holds every open job.
That's the DIY route, and it works for a handful of companies you already know. If you'd rather not build and maintain a Jobvite scraper, CleanJobData already ingests ATS platforms and company career sites and serves the jobs normalized through one REST API — see the Jobs API docs.
At a Glance
| Endpoint | GET https://jobs.jobvite.com/{company}/jobs (HTML) |
| Job page | GET https://jobs.jobvite.com/{company}/job/{id} (JSON-LD) |
| API key | None |
| Pagination | None; one page lists every job |
| Full description | JSON-LD description on each job page |
| Salary field | JSON-LD baseSalary, often empty |
| Remote | No flag; infer from title and location |
Finding the Company Slug
Hosted Jobvite career pages live at https://jobs.jobvite.com/{company}/jobs, so a company at jobs.jobvite.com/acme/jobs has the slug acme. If a company's careers page sits on its own domain, look for links or requests to jobs.jobvite.com in the page source or the Network tab.
Listing Jobs
curl "https://jobs.jobvite.com/acme/jobs"The response is server-rendered HTML. Every job is a link of the form href="/acme/job/o4SaAfwq", and the part after /job/ is the job ID: a short alphanumeric string, not a number. Collect the IDs with a regex and dedupe them as you go.
The listing has no dates or descriptions, so everything else comes from the job pages. The page title reads "Acme Careers", which is a usable fallback for the company name.
The Job Page and Its JSON-LD
curl "https://jobs.jobvite.com/acme/job/o4SaAfwq"Each job page has a script type="application/ld+json" block with a JobPosting object. Trimmed:
{
"@context": "http://schema.org",
"@type": "JobPosting",
"title": "Production Partner",
"identifier": "o4SaAfwq",
"datePosted": "2026-05-22",
"hiringOrganization": "Acme Mortgage",
"employmentType": "Full-Time",
"industry": "Branch Operations",
"description": "<h1 style=\"margin: 0.0in;\">...</h1><p>...</p>",
"jobLocation": [
{
"@type": "Place",
"address": {
"@type": "PostalAddress",
"addressLocality": "Johnson City",
"addressRegion": "Tennessee",
"addressCountry": "United States"
}
}
],
"baseSalary": {
"@type": "MonetaryAmount",
"currency": "",
"value": { "@type": "QuantitativeValue", "minValue": "", "maxValue": "", "unitText": "Annually" }
}
}| Field | What it is |
|---|---|
title | Job title |
identifier | Job ID; usually the same as the URL ID |
datePosted | Posting date, sometimes date only |
description | Full description, HTML |
jobLocation | One or more Place objects with addressLocality, addressRegion, addressCountry |
hiringOrganization | Company name, as a string or an object with name |
employmentType | For example "Full-Time" |
baseSalary | Pay range with currency, minValue, maxValue, unitText, when filled in |
For the full field reference, see our JobPosting schema guide. The apply page is the job URL with /apply added.
Fetching Jobs (Python)
import json
import re
import requests
LD_JSON = re.compile(r'<script[^>]+type="application/ld\+json"[^>]*>(.*?)</script>', re.S | re.I)
def list_jobvite_ids(company: str) -> list[str]:
html = requests.get(f"https://jobs.jobvite.com/{company}/jobs", timeout=20).text
ids = re.findall(rf'href="/{re.escape(company)}/job/([^"?]+)', html)
return list(dict.fromkeys(ids)) # dedupe, keep order
def parse_job_posting(html: str) -> dict | None:
for block in LD_JSON.findall(html):
try:
ld = json.loads(block)
except json.JSONDecodeError:
continue
if ld.get("@type") == "JobPosting":
return ld
return None
def fetch_jobvite_jobs(company: str) -> list[dict]:
jobs = []
for job_id in list_jobvite_ids(company):
html = requests.get(f"https://jobs.jobvite.com/{company}/job/{job_id}", timeout=20).text
ld = parse_job_posting(html)
if not ld:
continue
org = ld.get("hiringOrganization")
places = ld.get("jobLocation") or []
if isinstance(places, dict):
places = [places]
salary = ld.get("baseSalary") or {}
value = salary.get("value") or {}
jobs.append({
"id": ld.get("identifier") or job_id,
"url_id": job_id,
"title": ld.get("title"),
"company": org.get("name") if isinstance(org, dict) else org,
"posted": ld.get("datePosted"),
"description_html": ld.get("description"),
"locations": [
", ".join(filter(None, [a.get("addressLocality"), a.get("addressRegion"), a.get("addressCountry")]))
for a in ((p or {}).get("address") or {} for p in places)
],
"salary_min": value.get("minValue") or None, # "" means not set
"salary_max": value.get("maxValue") or None,
"salary_currency": salary.get("currency") or None,
"salary_unit": value.get("unitText") or None,
"url": f"https://jobs.jobvite.com/{company}/job/{job_id}",
})
return jobsFetch job pages a few at a time, not all at once. A board with a few hundred jobs means a few hundred page requests.
Gotchas
Empty salary placeholders. baseSalary can be present with empty strings for currency, minValue and maxValue. Treat empty strings as "not published" rather than zero.
unitText isn't always a schema.org value. The format suggests HOUR, DAY, WEEK, MONTH or YEAR, but we've seen words like "Annually" on Jobvite pages. Match loosely ("hour", "annual", "year", "month") before you annualize. See the salary extraction guide.
hiringOrganization changes shape. It can be a plain string or an object with a name. Handle both.
Old dates on evergreen postings. datePosted can be date-only, and reposted "General Application" style postings carry dates that are years old. Decide whether to keep jobs past a certain age; you can only check after fetching the job page, because the listing has no dates.
Full names, not codes. addressCountry is a full country name like "United States" and addressRegion a full state name like "Tennessee". Convert them if you store ISO codes. A job can have several jobLocation entries, each with its own country, so keep them all. The location normalization guide covers the matching.
The ID can differ between the URL and the JSON-LD. On most boards identifier equals the ID in the job URL, but not on every one. Store both, or you'll match the wrong key when you compare the listing with what you've stored.
Descriptions carry inline styles. Descriptions can arrive with inline style attributes and fonts from whatever editor the recruiter used. Strip or sanitize them before you render.
No remote flag. Check the title and location for "remote" or "hybrid".
Career Pages vs Jobvite's Official API
Jobvite offers APIs to its customers, with credentials issued through the employer's Jobvite account. They cover the employer's own recruiting data. For published jobs at companies you don't have that relationship with, the public career pages and their JSON-LD are the source, which is the approach above.
When This Is Enough
For one company, a listing request plus one job page per new ID is simple, and the JSON-LD gives you clean fields without parsing the visible page.
When It Isn't
Across many companies, you're fetching one page per job and handling empty salaries, mixed field shapes and full country names, before you add other HTML-based platforms like iCIMS and Taleo. See which ATS have a public job postings API for how they compare.
CleanJobData reads Jobvite career pages alongside other platforms and returns one schema, with parsed salary when it's published, locations resolved to cities, states and countries, and a remote type. Try it in the Playground or see the API Documentation.
Skip the scraper: get this data from the CleanJobData API
If you'd rather not maintain a Jobvite collector, you can query normalized jobs from ATS platforms and company career sites with a single request. The response has structured city/state/country locations, parsed salary when the employer publishes one, a remote type, and company metadata, and you page through results with the cursor in pagination.next_page.
curl "https://api.cleanjobdata.com/jobs?title=engineer&domain=jobs.jobvite.com&limit=20" \
-H "Authorization: Bearer $CLEANJOBDATA_API_KEY"The domain filter is an exact match on the host of each job's application_url, so it only returns jobs whose apply link resolves to jobs.jobvite.com; use company_website_url or employer_id to scope to one employer instead. Coverage depends on which employers are in the dataset, so check that the companies you care about appear before you rely on it.
- Jobs API reference for every filter and response field
- Playground to run queries without writing code
- Pricing — the Trial is free with no card required
FAQ
Does Jobvite have a public jobs API?
No public JSON one. The hosted career page at https://jobs.jobvite.com/{company}/jobs lists every job link, and each job page has a schema.org JobPosting JSON-LD block you can parse. Jobvite's own APIs need credentials from the employer's account.
Do I need to paginate the Jobvite job list?
No. The /jobs page lists every open job on one page, so you collect all the IDs from a single request and then fetch each job page.
Does Jobvite include salary?
Sometimes. The JSON-LD can have a baseSalary with a range, currency and unitText, but it's often present with empty values, so check that the numbers are filled in before you use them.
How do I get the posting date for a Jobvite job?
Read datePosted from the job page's JSON-LD. The listing page has no dates, and some evergreen postings carry dates that are years old.