SAP SuccessFactors Jobs API

Read job postings from public SAP SuccessFactors career sites as structured JSON, with no API key and no SAP login. A SuccessFactors career site such as jobs.sap.com publishes its whole live job list as one public feed, and this API reads that feed, so a single request returns every open role on the site: requisition ID, title, employer, job function, location, country code and expiration date. Descriptions come back as Markdown by default, or as the original HTML or plain text. The feed has no posted date, so an optional add-on opens each job's own page for the posted date, department, facility, shift type and travel requirement. Title, job function, location, remote and active-only filters run before billing, so a filtered job costs nothing.

MEDIAN LAGon demand
FIELDS39
TOTAL USERS3
MONTHLY ACTIVE2
TOTAL RUNS44
SUCCESS (30D)100.0%
RATINGno ratings yet
LAST MODIFIED2026-10-04
PUBLISHED2026-09

Input parameters

PARAMETERTYPEREQDEFAULTDESCRIPTION
companies string[] no — Career-site hosts (jobs.sap.com), full career-site URLs, single job URLs (/job///) or company names, mixed freely. A host or URL resolves directly; a company name is matched against the bundled tenant directory. Leave it and startUrls empty to sweep the directory instead.
startUrls string[] no — The same career-site and single-job URLs in URL-list form, merged with companies.
outputMode enum no jobs jobs (full job records), urlsOnly (the job index without descriptions, the cheapest way to list everything) or tenantsOnly (one row per career site with a live open-jobs count).
discoveryQuery string no — Case-insensitive text matched against company names and tenant keys in the bundled directory. Scopes tenantsOnly runs and empty-input sweeps.
verifyTenants boolean no true tenantsOnly mode: probe each career site's live feed first and add a current job count. Dead sites are skipped and never billed.
titleKeywords string[] no — Keep only jobs whose title contains any of these, for example engineer or sales. Case-insensitive, and every filter runs before billing.
jobFunctions string[] no — Keep only jobs whose job function contains any of these, for example Development, Sales or Administration.
locationKeywords string[] no — Keep only jobs whose location string contains any of these, for example Berlin, Bangalore or Remote.
activeOnly boolean no true Drop postings whose expiration date has already passed.
remoteOnly boolean no false Keep only jobs whose title or location reads as remote: remote, anywhere, work from home or virtual.
includeDescriptionMarkdown boolean no true Add descriptionMarkdown, the posting converted to Markdown. A paid add-on billed per job row that carries it; turn it off for metadata-only rows.
includeDescriptionHtml boolean no false Add descriptionHtml, the original posting markup. A paid add-on billed per row that carries it.
includeDescriptionText boolean no false Add descriptionText, a clean plain-text rendering. A paid add-on billed per row that carries it.
includeDetailFields boolean no false Open each job's own page for datePosted, department, facility, shiftType, travel and customFields. One extra request per job, so large runs are slower. A paid add-on billed per row that carries the data.
report enum no none none, markdown or html. Writes a digest of the run's jobs, grouped by company, to the key-value store under REPORT. One flat charge, capped at 5,000 rows.
maxTenants integer no 25 Cap on career sites processed in a directory sweep or a tenantsOnly run, 1 to 50,000.
maxJobsPerTenant integer no 0 Cap on job rows per career site after filtering. 0 means no per-site cap.
maxJobs integer no 100 Hard ceiling on billable rows across the whole run, all career sites combined. The main cost control; 0 means unlimited. — drives your bill
maxConcurrency integer no 5 Parallel detail-page fetches when the detail add-on is on, and parallel probes in discovery, 1 to 10. Reading a career site's feed is always one request.

Output schema

FIELDTYPEDESCRIPTIONNULLABLE
resultType string What this row is: job (a full job record), url (a job index row), tenant (a discovered career site) or error (a career site or job that could not be read, never billed). no
requisitionId string The career site's public requisition ID for the posting. yes
title string The posting title. yes
companyName string The hiring company: the feed's employer field, else the directory name, else the career-site host. yes
employer string The employer name exactly as the feed publishes it. yes
tenant string The career-site host this row came from, for example jobs.sap.com. yes
careerSiteUrl string The career site's home URL. yes
url string Canonical public URL of the posting. Dedupe key. yes
applyUrl string The application page for the posting. yes
jobFunction string The job function as the feed publishes it. yes
location string The location string, usually city, two-letter country code and postcode. yes
countryCode string Two-letter country code parsed from the location string, when present. yes
validThrough string The posting's expiration date (ISO date). The field behind activeOnly. yes
isRemote boolean Remote flag inferred from words in the title and location. Null when both are empty. yes
datePosted string The date the posting went live (ISO date). Detail add-on only; the feed does not carry it. yes
department string Department from the job's own page. Detail add-on only. yes
facility string Facility identifier from the job's own page. Detail add-on only. yes
shiftType string Shift or work-time type from the job's own page. Detail add-on only. yes
travel string Travel requirement from the job's own page, for example 0 - 10%. Detail add-on only. yes
customFields object Employer-defined fields from the job's own page. Detail add-on only. yes
salaryDerived object Salary range parsed from the description text when it states one: min, max, currency, period and source. yes
salaryMin number Lower bound of the parsed salary range, flattened for tables and CSV. yes
salaryMax number Upper bound of the parsed salary range. yes
salaryCurrency string Currency code of the parsed salary range. yes
salaryPeriod string Pay period of the parsed range: year, month, week, day or hour. yes
descriptionMarkdown string The posting converted to Markdown. Present when the Markdown add-on is on. yes
descriptionHtml string The original posting markup from the feed. Present when the HTML add-on is on. yes
descriptionText string A plain-text rendering of the posting. Present when the text add-on is on. yes
flavor string The SuccessFactors site variant the row came from: rmk, for Recruiting Marketing career sites. yes
source string Always successfactors, for merging with other ATS datasets. yes
sourceType string Always ats. yes
sourceUrl string The input entry that produced the row, when it was a URL. yes
jobCount integer Tenant rows: live jobs in the career site's feed at verification time. yes
live boolean Tenant rows: whether the feed answered the live probe. Null when verification was off. yes
verifiedAt string Tenant rows: when the live probe ran (ISO 8601). yes
errorCode string Error rows: invalid_url, tenant_not_found, job_not_found, http_error, invalid_input or run_failed. yes
errorMessage string Error rows: a readable explanation, safe to display. yes
didYouMean string[] Error rows: the closest known tenant keys when a career site was not found. yes
scrapedAt string When the row was produced (ISO 8601, UTC). no

Worked examples

Basic — one career site, full job records with Markdown descriptions
{"companies": ["jobs.sap.com"], "maxJobs": 25}
Engineering roles in two cities — filters run before billing, so dropped jobs cost nothing
{"companies": ["jobs.sap.com"], "titleKeywords": ["engineer", "developer"], "locationKeywords": ["Walldorf", "Berlin"], "maxJobs": 100}
Index every open job cheaply — links and expiration dates, no descriptions
{"companies": ["jobs.sap.com"], "outputMode": "urlsOnly", "maxJobs": 0}
Posted date and department — one extra request per job, billed only on rows that carry the fields
{"companies": ["jobs.sap.com"], "includeDetailFields": true, "includeDescriptionMarkdown": false, "maxJobs": 20}
Live open-jobs count per career site — one tenant row per site, dead sites unbilled
{"outputMode": "tenantsOnly", "companies": ["jobs.sap.com"]}
POWER-USER TIP
Markdown is on by default, and billed — A default job row carries a Markdown description, so it bills the job price plus the Markdown add-on. Set includeDescriptionMarkdown to false for title, location, job function and expiration only, or use outputMode urlsOnly for the cheapest index of a site.
POWER-USER TIP
Pass the career-site host — A host such as jobs.sap.com, a full career-site URL or a single job URL resolves directly. A company name is only matched against the bundled directory, and a miss comes back as an unbilled tenant_not_found row with didYouMean suggestions, so a host is the reliable input. Older portals on hosts of the form careerN.successfactors.com are not read yet.
POWER-USER TIP
The feed has no posted date — Each career site's feed carries an expiration date but no posted date. datePosted, department, facility, shift type and travel come from the job's own page through includeDetailFields, at one extra request per job. To catch new postings without it, diff requisitionId between scheduled runs.
POWER-USER TIP
Filter on a city, not a country name — Location strings read like Prague 5, CZ, 158 00: city, two-letter country code and postcode. locationKeywords matches substrings, so filter on a city or region name, and group by the countryCode field after the run.
POWER-USER TIP
Salary is parsed from the text — The feed has no pay field. salaryMin and salaryMax come from a fixed pattern match on the description when it states a range such as $90,000 - $120,000, and stay null otherwise. Nothing is inferred by a model.

Coverage

1
requests to read a whole career site — the detail add-on adds one request per job
3
output modes — full job records, job URLs only, career-site discovery
3
description formats — Markdown (on by default), HTML, plain text
5,000
jobs in a run report, at most — the REPORT digest stops there; the dataset does not

Code

Read a career site in one call

curl -X POST "https://api.apify.com/v2/acts/johnvc~sap-successfactors-jobs-api/run-sync-get-dataset-items" \
  -H "Authorization: Bearer $APIFY_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"companies": ["jobs.sap.com"], "titleKeywords": ["engineer"], "maxJobs": 50}'

Python

from apify_client import ApifyClient

client = ApifyClient("APIFY_TOKEN")
run = client.actor("johnvc/sap-successfactors-jobs-api").call(
    run_input={"companies": ["jobs.sap.com"], "titleKeywords": ["engineer"], "maxJobs": 50}
)
for row in client.dataset(run.default_dataset_id).iterate_items():
    if row.get("resultType") == "error":
        print("error:", row.get("errorCode"), row.get("errorMessage"))
    else:
        print(row.get("title"), "|", row.get("location"), "|", row.get("validThrough"), "|", row.get("url"))

MCP

claude mcp add --transport http successfactors-jobs \
  "https://mcp.apify.com/?tools=actors,docs,johnvc/sap-successfactors-jobs-api"

Sample job row (synthetic)

{
  "resultType": "job",
  "requisitionId": "1400000001",
  "title": "Senior Data Engineer",
  "companyName": "Example Corp",
  "employer": "Example Corp",
  "tenant": "jobs.example.com",
  "careerSiteUrl": "https://jobs.example.com",
  "url": "https://jobs.example.com/job/Berlin-Senior-Data-Engineer/1400000001/",
  "applyUrl": "https://jobs.example.com/job/Berlin-Senior-Data-Engineer/1400000001/",
  "jobFunction": "Development",
  "location": "Berlin, DE, 10115",
  "countryCode": "DE",
  "validThrough": "2026-11-30",
  "isRemote": false,
  "salaryMin": null,
  "salaryMax": null,
  "descriptionMarkdown": "**About the role**\n\nExample Corp is hiring a senior data engineer to build its reporting pipelines.",
  "flavor": "rmk",
  "source": "successfactors",
  "sourceType": "ats",
  "scrapedAt": "2026-10-09T14:00:00Z"
}

What people use it for

  • Backfilling a job board from enterprise ATS sites
  • Sales prospecting on enterprise hiring activity
  • Feeding an AI recruiting agent Markdown job descriptions
  • Tracking new requisitions on a SuccessFactors site by diffing IDs between runs
  • Breaking down an employer's open roles by department, facility and shift type
  • Indexing every open requisition on a career site without descriptions

More sources for Hiring signals and talent intelligence, Grounding AI agents and MCP tools →

Alternatives