PeopleMatter (Snagajob) Jobs API.

Reach high-volume hourly and frontline job listings from the restaurant, retail, and hospitality brands that hire through Snagajob's enterprise platform. Jobo turns tenant apply pages into clean, structured job data.

Get API access

What's in every response.

Data fields, real-world applications, and the companies already running on PeopleMatter (Snagajob).

Data fields

  • Job Titles & Roles
  • Store & Site Locations
  • Employer / Brand Name
  • Full Job Descriptions
  • Stable Job UUIDs
  • Hourly & Frontline Positions

Use cases

  1. 01Hourly Job Aggregation
  2. 02Restaurant & Retail Hiring Feeds
  3. 03Frontline Labor Market Data
  4. 04Franchise Location Tracking
DIY GUIDE

How to scrape PeopleMatter (Snagajob).

Step-by-step guide to extracting jobs from PeopleMatter (Snagajob)-powered career pages—endpoints, authentication, and working code.

API type
HTML
Difficulty
advanced
Rate limit
No published limit; ~500ms between requests recommended
Authentication
No auth

Recognize and parse PeopleMatter apply URLs

PeopleMatter job links share one canonical shape on the api.peoplematter.com host. Validate the host and path, then pull the tenant from the first path segment and the job UUID from the jobOpeningId query parameter.

Step 1: Recognize and parse PeopleMatter apply URLs
import re
from urllib.parse import urlparse, parse_qs

APPLY_RE = re.compile(
    r"^https://api\.peoplematter\.com/(?P<tenant>[^/]+)/Hire/Recruiting/Application/Index",
    re.IGNORECASE,
)

def parse_apply_url(url: str):
    """Return {tenant, job_opening_id} for a PeopleMatter apply URL, else None."""
    match = APPLY_RE.match(url)
    if not match:
        return None
    query = parse_qs(urlparse(url).query)
    return {
        "tenant": match.group("tenant"),          # e.g. "mattiaciogroup", "KFCPPP0001225"
        "job_opening_id": query.get("jobOpeningId", [None])[0],  # UUID
    }

print(parse_apply_url(
    "https://api.peoplematter.com/mattiaciogroup/Hire/Recruiting/Application/Index"
    "?jobOpeningId=d7944c9c-c189-421d-8b02-a9540112218d"
))

Follow the redirect to the provider-owned job page

The api.peoplematter.com apply URL redirects to the server-rendered application page on my.peoplematter.com (mja/{tenant}/jobapp/GetStarted). Follow redirects and keep the final URL as the canonical job page. No login is required.

Step 2: Follow the redirect to the provider-owned job page
import requests

UA = "Mozilla/5.0 (compatible; JoboBot/1.0; +https://jobo.world)"

def resolve_job_page(apply_url: str) -> requests.Response:
    resp = requests.get(
        apply_url,
        headers={"User-Agent": UA},
        allow_redirects=True,   # api.peoplematter.com -> my.peoplematter.com/mja/...
        timeout=30,
    )
    resp.raise_for_status()
    return resp

resp = resolve_job_page(
    "https://api.peoplematter.com/mattiaciogroup/Hire/Recruiting/Application/Index"
    "?jobOpeningId=d7944c9c-c189-421d-8b02-a9540112218d"
)
print(resp.url)  # final my.peoplematter.com application URL

Extract job fields from the rendered HTML

The redirected page is server-rendered HTML that exposes the job title, location, company, and a job-description control without authentication. Use defensive selectors, since PeopleMatter does not publish a stable class contract.

Step 3: Extract job fields from the rendered HTML
from bs4 import BeautifulSoup

def extract_job(resp: requests.Response, parsed: dict) -> dict:
    soup = BeautifulSoup(resp.text, "html.parser")
    title_el = soup.find("h1") or soup.find(attrs={"class": re.compile("title", re.I)})
    desc_el = soup.select_one("[class*='description'], [id*='description']")
    return {
        "job_opening_id": parsed["job_opening_id"],   # stable UUID key
        "tenant": parsed["tenant"],
        "url": resp.url,
        "title": title_el.get_text(strip=True) if title_el else None,
        "description_html": str(desc_el) if desc_el else None,
    }

Seed discovery and deduplicate by UUID

PeopleMatter exposes an organization landing route at my.peoplematter.com/{businessAlias}/hire, but job selection is a multi-step location -> job workflow with no stable anonymous listing JSON. Enumerate from known apply URLs and terminate when no new jobOpeningId UUIDs appear.

Step 4: Seed discovery and deduplicate by UUID
def hire_landing(business_alias: str) -> str:
    # Documented org route; selection is a multi-step location -> job workflow.
    return f"https://my.peoplematter.com/{business_alias}/hire"

def collect(apply_urls: list[str]) -> list[dict]:
    seen: set[str] = set()
    jobs: list[dict] = []
    for url in apply_urls:
        parsed = parse_apply_url(url)
        if not parsed or parsed["job_opening_id"] in seen:
            continue          # skip malformed or duplicate UUIDs across tenants
        seen.add(parsed["job_opening_id"])
        jobs.append(extract_job(resolve_job_page(url), parsed))
    return jobs
Common issues
mediumLegacy api.peoplematter.com apply URLs redirect to my.peoplematter.com and appear broken if redirects are disabled.
Send requests with allow_redirects=True and treat the final my.peoplematter.com/mja/{tenant}/jobapp/GetStarted URL as the canonical job page.
highThere is no stable anonymous listing JSON endpoint; the organization /hire route is a multi-step location-then-job workflow.
Seed enumeration from known apply URLs (jobOpeningId UUIDs) rather than a directory feed, and stop discovery when no new UUIDs surface. Use Jobo's maintained tenant coverage to avoid rebuilding the hire workflow.
mediumPeopleMatter was historically fronted by Cloudflare with country/ASN filtering that returned 403s from some networks.
The block no longer reproduces on plain HTTP, but keep a descriptive User-Agent and retry-with-backoff on transient 403s in case filtering recurs from datacenter egress.
lowTenant aliases vary widely in format (e.g. mattiaciogroup vs KFCPPP0001225) and the job id lives in the query string, not the path.
Treat the first path segment as an opaque tenant token and read the UUID from the jobOpeningId query parameter; strip the query before glob/path matching.
Best practices
  1. 1Follow HTTP redirects and treat the final my.peoplematter.com URL as the canonical job page.
  2. 2Extract the tenant from the first path segment and the jobOpeningId UUID from the query string; treat both as opaque.
  3. 3Pace requests around 500ms apart and cap concurrency near 2 detail fetches to stay polite.
  4. 4Send a descriptive User-Agent and retry on transient 403s in case Cloudflare filtering recurs.
  5. 5Deduplicate jobs by their jobOpeningId UUID, since the same role can surface across franchise tenants.
  6. 6Fall back to Jobo's normalized feed instead of reconstructing the multi-step hire workflow yourself.
Or skip the complexity

One endpoint. All PeopleMatter (Snagajob) jobs. No scraping, no sessions, no maintenance.

Get API access
cURL
curl "https://connect.jobo.world/api/jobs?sources=peoplematter (snagajob)" \
  -H "X-Api-Key: YOUR_KEY"
Developer tools

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.

Ready to integrate

Access PeopleMatter (Snagajob)
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.

99.9%API uptime
<200msAvg response
50M+Jobs processed