- highThe board returns links belonging to a different company
- Apploi boards can carry cross-promoted anchors from sibling facilities under the same operator. Always compare the company segment of /job/{jobId}/{companyToken}/{slug} against the board token you requested and drop anything that does not match, or one facility's snapshot will absorb another's jobs.
- mediumA detail page has no JobPosting JSON-LD
- Draft, expired or partially configured postings render the page shell without the structured block. Treat a missing JobPosting as a parse failure for that job rather than a removal, and retry it on the next run before deciding the vacancy is gone.
- mediumThe public board and Apploi's partner API are not the same thing
- Apploi's documented jobs API requires a vendor-issued x-api-key and is not open to the public. Everything shown here reads the same anonymous pages a candidate sees; do not expect key-only fields such as pipeline status or applicant data to appear in the JSON-LD.
- lowShort /view/ links break tenant attribution
- jobs.apploi.com/view/{id} URLs contain no company token, so a naive parse assigns the job to no board at all. Follow the redirect to apply-jobs.apploi.com and take the company from the final URL before writing the record.
Apploi Jobs API.
Apploi is a hiring platform for healthcare and senior-living employers. Its public company boards render every job link server-side, and each detail page carries canonical JobPosting JSON-LD — no key required.
What's in every response.
Data fields, real-world applications, and the companies already running on Apploi.
Data fields
- Full Job Descriptions
- JobPosting JSON-LD
- Employment Type
- Facility Locations
- Posted Dates
- Direct Apply URLs
Use cases
- 01Healthcare Job Aggregation
- 02Senior Living Hiring Trackers
- 03Nursing Recruitment Feeds
- 04Local Labour Market Research
How to scrape Apploi.
Step-by-step guide to extracting jobs from Apploi-powered career pages—endpoints, authentication, and working code.
from urllib.parse import urlparse
HOST = "apply-jobs.apploi.com"
def parse_apploi(url: str):
"""Return (company_token, job_id) from any canonical Apploi URL."""
parsed = urlparse(url)
if parsed.netloc.lower() != HOST:
return None
segments = [s for s in parsed.path.split("/") if s]
if len(segments) >= 2 and segments[0] == "jobs":
return segments[1].lower(), None
if len(segments) >= 4 and segments[0] == "job":
# /job/{jobId}/{companyToken}/{slug}
return segments[2].lower(), segments[1]
return None
print(parse_apploi("https://apply-jobs.apploi.com/job/531470/lincoln-park/dietary-porter"))
# ('lincoln-park', '531470')import requests
from bs4 import BeautifulSoup
from urllib.parse import urljoin
def fetch_board(session, company_token: str) -> list[dict]:
board_url = f"https://{HOST}/jobs/{company_token}"
resp = session.get(board_url, headers={"Accept": "text/html"}, timeout=30)
resp.raise_for_status()
soup = BeautifulSoup(resp.text, "html.parser")
listings, seen = [], set()
for anchor in soup.select("a[href]"):
parsed = parse_apploi(urljoin(f"https://{HOST}", anchor["href"]))
if not parsed:
continue
token, job_id = parsed
if job_id is None or token != company_token or job_id in seen:
continue
seen.add(job_id)
listings.append({
"id": job_id,
"title": " ".join(anchor.get_text().split()),
"url": urljoin(f"https://{HOST}", anchor["href"]).split("?")[0],
})
return listings
session = requests.Session()
listings = fetch_board(session, "lincoln-park")
print(f"{len(listings)} open jobs")import json
import time
def find_job_posting(html: str) -> dict | None:
soup = BeautifulSoup(html, "html.parser")
for tag in soup.find_all("script", type="application/ld+json"):
try:
data = json.loads(tag.string or "")
except (json.JSONDecodeError, TypeError):
continue
for node in (data if isinstance(data, list) else [data]):
if isinstance(node, dict) and node.get("@type") == "JobPosting":
return node
return None
def fetch_detail(session, listing: dict) -> dict | None:
resp = session.get(listing["url"], headers={"Accept": "text/html"}, timeout=30)
if resp.status_code in (404, 410):
return None # posting removed
resp.raise_for_status()
posting = find_job_posting(resp.text)
if not posting:
return None
address = ((posting.get("jobLocation") or {}).get("address")) or {}
return {
"id": listing["id"],
"title": posting.get("title") or listing["title"],
"description_html": posting.get("description"),
"employment_type": posting.get("employmentType"),
"posted_at": posting.get("datePosted"),
"closes_at": posting.get("validThrough"),
"city": address.get("addressLocality"),
"state": address.get("addressRegion"),
"country": address.get("addressCountry"),
"url": listing["url"],
"apply_url": listing["url"],
}
for listing in listings[:3]:
print(fetch_detail(session, listing))
time.sleep(0.25)def resolve_short_link(session, url: str) -> dict | None:
"""Turn https://jobs.apploi.com/view/531470 into a board + job identity."""
resp = session.get(url, headers={"Accept": "text/html"}, timeout=30,
allow_redirects=True)
if not resp.ok:
return None
parsed = parse_apploi(str(resp.url))
if not parsed:
return None
company_token, job_id = parsed
original_id = [s for s in url.split("/") if s][-1]
return {
"company_token": company_token,
"job_id": job_id or original_id,
"board_url": f"https://{HOST}/jobs/{company_token}",
}
print(resolve_short_link(session, "https://jobs.apploi.com/view/531470"))- 1Deduplicate on the numeric job ID from /job/{jobId}/ — titles repeat across shifts
- 2Reject any anchor whose company segment differs from the board you requested
- 3Read the JobPosting JSON-LD rather than the themed markup, which varies per employer
- 4Follow jobs.apploi.com/view/ redirects to recover the owning company board
- 5Throttle to ~250ms between requests and keep concurrent detail fetches at three
- 6Re-check a missing JSON-LD block on the next run before marking a job closed
One endpoint. All Apploi jobs. No scraping, no sessions, no maintenance.
Get API accesscurl "https://connect.jobo.world/api/jobs?sources=apploi" \
-H "X-Api-Key: YOUR_KEY"Try the API.
Test Jobs and Feed endpoints against https://connect.jobo.world with live request/response examples, then copy ready-to-use curl commands.
Access Apploi
job data today.
One API call. Structured data. No scraping infrastructure to build or maintain — start with the $5 free starting balance and scale as you grow.