Integrations / SAP SuccessFactors (basic authentication)
SAP SuccessFactors (basic authentication)
SuccessFactors with basic authentication (older tenants): HR and talent data over the OData v2 API: users, Employee Central person, employment and job records, departments, locations, recruiting (requisitions, applications, candidates), time off, counts, a guarded read of any OData path, and Upsert for writes. For tenants that still use HTTP basic authentication (username@companyId and password). SAP deprecates basic authentication for APIs and deletes it in November 2027 (off by default in 1H 2027): use the sap_successfactors toolkit (IAS OIDC) for anything new. api_host is the SuccessFactors API server of the tenant's data centre (e.g. api2.successfactors.eu, api4.successfactors.com, api8.successfactors.com, api10.successfactors.com, api012.successfactors.eu, api15.sapsf.cn, api16.sapsf.eu, api17.sapsf.com, api18.sapsf.com, api19.sapsf.com, api22.sapsf.com, api23.sapsf.com, api41.sapsf.com, api42.sapsf.com, api44.sapsf.com, api47.sapsf.com, api50.sapsf.com, api55.sapsf.eu, api74.sapsf.eu (preview systems use apiXpreview.sapsf.com/.eu; the full list is table 1.1 'List of SAP SuccessFactors API Servers' in the API Reference Guide and SAP KBA 2215682)). Customer-specific: each tenant's own address, permissions (Role-Based Permissions) and, usually, IP allow-listing apply, so a hosted Setu needs its egress IPs allowed. Request shapes follow SAP's API Reference Guide; Setu has not verified them against a live SuccessFactors tenant.
Connect
const conn = await setu.connections.initiate({ userId: "user_1", toolkit: "sap_successfactors_basic" });
console.log(conn.connectUrl); // show this to your user
await conn.waitUntilActive();Permissions requested
This toolkit uses a single credential and requests no scopes.
Actions
Count recordsreadsap_successfactors_basic.count_entityCount the records of any OData v2 entity (GET /odata/v2/<Entity>/$count), optionally with a filter, for example entity User with filter status eq 'f'. Returns the number.
| Input | Type | Description | |
|---|---|---|---|
entity | string | Required | Entity name such as User, PerPerson, EmpJob, Position, JobRequisition. |
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.count_entity",
input: {
"entity": "<entity>"
},
});Get userreadsap_successfactors_basic.get_userGet one SuccessFactors user by user id (OData User('id')). Use expand for related records such as manager or hr, and select to limit fields.
| Input | Type | Description | |
|---|---|---|---|
user_id | string | Required | The userId, for example cgrant. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.get_user",
input: {
"user_id": "<user_id>"
},
});List candidatesreadsap_successfactors_basic.list_candidatesList candidates (people in the recruiting database) (Recruiting entity Candidate). Needs Recruiting API permissions; field names depend on the tenant's configuration, so use odata_get with a /$metadata path to discover them if unsure. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_candidates",
input: {},
});List departmentsreadsap_successfactors_basic.list_departmentsList departments (Foundation Object FODepartment, effective-dated). Documented fields include externalCode, name, description, parent, costCenter, headOfUnit, status (A active). Filter example: externalCode eq '50150016'. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
as_of_date | string | Optional | Effective-dated entities: return the records valid on this date (yyyy-MM-dd) (asOfDate). |
from_date | string | Optional | Effective-dated entities: start of a date range (yyyy-MM-dd) (fromDate). |
to_date | string | Optional | Effective-dated entities: end of a date range (yyyy-MM-dd) (toDate). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_departments",
input: {},
});List employees (PerPerson)readsap_successfactors_basic.list_employeesList Employee Central person records (OData PerPerson). Use filter personIdExternal eq '10001' for one person and expand navigations such as personalInfoNav, emailNav or phoneNav to embed personal data, emails and phones (the guide's example is PerPerson?$filter=personIdExternal eq 'cgrant1'&$expand=emailNav). Needs Employee Central API permissions. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_employees",
input: {},
});List employment inforeadsap_successfactors_basic.list_employment_infoList employment records (OData EmpEmployment: one per person and employment, with hire and termination details). Filter by personIdExternal or userId and expand navigations such as jobInfoNav to include the job record. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_employment_info",
input: {},
});List job applicationsreadsap_successfactors_basic.list_job_applicationsList job applications (a candidate's application to a requisition) (Recruiting entity JobApplication). Needs Recruiting API permissions; field names depend on the tenant's configuration, so use odata_get with a /$metadata path to discover them if unsure. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_job_applications",
input: {},
});List job inforeadsap_successfactors_basic.list_job_infoList job information records (OData EmpJob, effective-dated: position, department, manager, location per period). Use as_of_date for the record valid on a day, or from_date/to_date for history, and filter by userId. Expand departmentNav to embed the department (documented example EmpJob?asOfDate=2020-03-30&$expand=departmentNav). Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
as_of_date | string | Optional | Effective-dated entities: return the records valid on this date (yyyy-MM-dd) (asOfDate). |
from_date | string | Optional | Effective-dated entities: start of a date range (yyyy-MM-dd) (fromDate). |
to_date | string | Optional | Effective-dated entities: end of a date range (yyyy-MM-dd) (toDate). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_job_info",
input: {},
});List job requisitionsreadsap_successfactors_basic.list_job_requisitionsList job requisitions (open and closed positions being hired for) (Recruiting entity JobRequisition). Needs Recruiting API permissions; field names depend on the tenant's configuration, so use odata_get with a /$metadata path to discover them if unsure. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_job_requisitions",
input: {},
});List locationsreadsap_successfactors_basic.list_locationsList locations (Foundation Object FOLocation, effective-dated). externalCode is the location code (for example US_ATL). Use select=externalCode,name to keep the answer short. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
as_of_date | string | Optional | Effective-dated entities: return the records valid on this date (yyyy-MM-dd) (asOfDate). |
from_date | string | Optional | Effective-dated entities: start of a date range (yyyy-MM-dd) (fromDate). |
to_date | string | Optional | Effective-dated entities: end of a date range (yyyy-MM-dd) (toDate). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_locations",
input: {},
});List time offreadsap_successfactors_basic.list_time_offList time-off records (Time Off entity EmployeeTime). Documented fields: userId, timeType, startDate, endDate, approvalStatus (for example APPROVED), quantityInDays, quantityInHours. Example filter: userId eq 'sampleemployee'. Dates come as /Date(ms)/ values. Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_time_off",
input: {},
});List usersreadsap_successfactors_basic.list_usersList or search SuccessFactors user accounts (OData entity User). Use filter such as status eq 'active', and select to limit fields (userId, username, firstName, lastName, email, department, status, hireDate, manager are documented User fields). Returns results plus next (an opaque link when more pages exist; pass top/skip to page) and count when inlinecount is allpages.
| Input | Type | Description | |
|---|---|---|---|
filter | string | Optional | OData $filter, for example: status eq 'active'. Quote string values with single quotes. |
select | string | Optional | Comma-separated fields to return ($select). Keep it short to save tokens. |
expand | string | Optional | Comma-separated navigation properties to embed ($expand). |
orderby | string | Optional | Sort order ($orderby), for example: lastName asc. Recommended together with skip. |
top | integer | Optional | Page size ($top); SuccessFactors returns at most 1000 records per request. |
skip | integer | Optional | Records to skip ($skip) for paging; use with orderby. |
inlinecount | string | Optional | Set to allpages to also get the total number of matching records (returned as count). |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.list_users",
input: {},
});OData read (any entity)readsap_successfactors_basic.odata_getGuarded read of any SuccessFactors OData path the person's role may see: path must start with /odata/v2/ (for example /odata/v2/Position, /odata/v2/User('cgrant')/manager, /odata/v2/$metadata) or /odatav4/ for OData v4 services. Pass OData options in query as plain values, for example {"$filter": "status eq 'active'", "$top": 10, "$format": "json"}. Use it for entities without a dedicated action (Position, EmpCompensation, Goals, PerPersonal). Read-only.
| Input | Type | Description | |
|---|---|---|---|
path | string | Required | Path such as /odata/v2/Position. Letters, digits and ._~-/'()$!*+,;=:@ only; no percent-encoding. |
query | object | Optional | Query parameters as plain text or numbers, for example $filter, $top, $skip, $select, $expand, $format, asOfDate. |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.odata_get",
input: {
"path": "<path>"
},
});Update userwritesap_successfactors_basic.update_userUpdate fields of an existing SuccessFactors user through Upsert (the documented way to change a User; the User entity has no delete, an account is set inactive with status). Send only the fields to change. Returns the per-record result (status OK or ERROR and a message); the call itself answers HTTP 200 even on a record error. Changes live HR data: confirm with the person first. The payload shape follows the guide's upsert example; whether every field can be omitted for an existing user depends on the tenant's configuration.
| Input | Type | Description | |
|---|---|---|---|
user_id | string | Required | The userId of the existing user. |
first_name | string | Optional | |
last_name | string | Optional | |
email | string | Optional | |
department | string | Optional | Department name as stored on the user. |
status | string | Optional | Account status, for example active or inactive. |
time_zone | string | Optional | Time zone, for example PST. |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.update_user",
input: {
"user_id": "<user_id>"
},
});Upsert recordswritesap_successfactors_basic.upsert_recordsCreate or update records of any entity with SuccessFactors Upsert (POST /odata/v2/upsert, a batch in one call). records is a JSON array; each item needs __metadata.uri naming the entity and key, for example {"__metadata": {"uri": "User('NewUser')"}, "userId": "NewUser", "username": "NewUser", "firstName": "Paul"}; navigation properties are referenced as {"manager": {"__metadata": {"uri": "User('OldManager')"}}}. The call returns HTTP 200 even when single records fail: check every item's status (OK or ERROR), editStatus (INSERTED, UPDATED) and message. Changes live HR data: confirm with the person first. Dates use "/Date(ms)/".
| Input | Type | Description | |
|---|---|---|---|
records | array of object | Required | Records to insert or update. |
await setu.execute({
userId: "user_1",
action: "sap_successfactors_basic.upsert_records",
input: {
"records": []
},
});