All platforms

SAP SuccessFactors Jobs API

Query jobs from SAP SuccessFactors boards through one API with ?source=successfactors — plus how SAP's sitemal.xml feed really behaves.

?source=successfactorssource reference

SAP SuccessFactors is the HR suite most of the SAP-shaped enterprise world runs on, and its careers sites are served by a product called Recruiting Marketing (formerly Jobs2Web, which is why so many of its hosts still carry that name). It's one of the largest sources in this dataset at 82,140 postings — a number that moves hourly, so read it from /v1/meta rather than trusting this sentence.

It is also, by a distance, the cheapest enterprise platform in this pool to collect: one unauthenticated GET returns a tenant's entire board with full descriptions.

Try it#

BASH
curl -G https://api.hyperjobs.io/v1/jobs \
  -H "Authorization: Bearer $HYPERJOBS_KEY" \
  --data-urlencode "source=successfactors" \
  --data-urlencode "time_frame=7d" \
  --data-urlencode "limit=2"
Illustrative — the shape, not a live response
{
  "data": [
    {
      "id": "successfactors:R-0041882",
      "title": "SAP Basis Administrator",
      "company": {
        "slug": "meridian-industries",
        "name": "Meridian Industries",
        "domain": "meridianindustries.com",
        "website": "https://meridianindustries.com",
        "logo": "https://media.licdn.com/dms/image/…",
        "industry": "Chemicals",
        "employee_count": 18500
      },
      "location": {
        "remote": false,
        "countries": ["Germany"],
        "cities": ["Walldorf"],
        "regions": null,
        "raw": ["Walldorf, Germany"]
      },
      "employment_type": null,
      "work_arrangement": null,
      "seniority": null,
      "salary": null,
      "skills": ["sap basis", "hana"],
      "taxonomies": ["IT"],
      "apply_url": "https://jobs.meridianindustries.com/job/Walldorf-SAP-Basis-Administrator/R-0041882",
      "url": "https://jobs.meridianindustries.com/job/Walldorf-SAP-Basis-Administrator/R-0041882",
      "source": "successfactors",
      "posted_at": "2026-07-11T06:22:10.000Z",
      "expires_at": null,
      "updated_at": "2026-07-14T06:22:10.000Z"
    }
  ],
  "total": 2,
  "limit": 2,
  "offset": 0
}

posted_at and expires_at are the interesting fields on this source, and both are explained below. Neither is what it looks like.

How SuccessFactors boards actually work#

One request per tenant. That's the whole thing:

BASH
curl "https://<recruiting-marketing-host>/sitemal.xml"

Yes, `sitemal.xml`

Not sitemap.xml. sitemal.xml is SAP's real path, and it is not a typo on this page — it's a typo in the product, shipped and now load-bearing. It's an RSS 2.0 feed rather than a sitemap: full <description> bodies plus Google-Merchant g: fields, unauthenticated, no pagination, no detail call.

The host is the employer's own careers domain (jobs.<company>.com, <company>.jobs2web.com, or a vanity name), which means there is no shared API host and no global index. Every tenant is found individually.

What each <item> carries:

FieldWhat it holds
descriptionThe full posting body, not a teaser
g:idThe requisition id
g:employerThe real employer name
g:locationPositional CSV: City[, State], ISO-CC[, postal]
g:salaryComp as posted, where posted
g:job_functionA clean category, ~93% fill

The <title> is Engineer II (Middlesex, GB) — title and location fused into one string, so the location has to be split back out of the parentheses. Nested parens happen (Title (City (0200), GB)), so a lazy match splits it wrong.

What bites you#

The feed has no date tag at all

There is no pubDate on a SuccessFactors item. Not "sometimes missing" — absent, on every job and every tenant. So a posting's real publish date is simply not in the feed, and the only honest thing to do is record when we first saw it.

That means posted_at on this source is a first-seen time, not SAP's datePosted. Recovering the true date would cost a detail fetch per posting, which is a steep price for a field that's already close for anything inside the freshness window. It's a source limitation, and it's worth knowing before you build a "posted in the last 24h" chart on it.

g:expiration_date is a lie, and we deliberately don't read it. It's present, it parses, and it's a synthetic constant: now + 30 days, on every job, on every tenant. It's a rolling default, not a real posting expiry. Store it and you ship an expires_at that is always exactly a month out and means nothing. Ours is null here unless the platform actually declared something.

g:location needs cleaning to resolve. It's positional, and it arrives as Clearwater, FL, US, 33762 or Walldorf, DE. The trailing token is sometimes a postal code and the one before it is an ISO-2 country. Feed that string to a geocoder as-is and the postal code and the bare country code both fuzz the match. We drop the postal token and expand DE to Germany so the country is deterministic rather than guessed.

The board token isn't the employer. g:employer is, and it's on every item. The host is often a vanity domain that says nothing about the legal entity behind it.

Or use ours#

This is the one enterprise platform where "just fetch it" is nearly true. One GET, no auth, no pagination, no N+1, full bodies. Descriptions land on 100% of the SuccessFactors rows we serve.

So the pitch isn't the fetch. It's that the feed doesn't publish a date and publishes a fake expiry, that its locations need decomposing before they resolve, that the useful employer name is a g: extension rather than anything standard, and that there is no list of tenants anywhere — every one of the boards behind these 82,140 postings was found individually, because SAP publishes no index of who its customers are.

You also get these rows deduplicated against the same job on LinkedIn or an employer's other boards, and the company join.

SuccessFactors sits in the heavy refresh tier, attempted every third cycle — see coverage.

Query it with ?source=successfactors. Quickstart · Pricing

Every source above normalises onto the same schema, with the hiring company already joined onto each posting.

Get an API key