Expand OData navigation properties in SAP Success Factors connector
AnsweredFivetran feature request - expand OData navigation properties (SAP SuccessFactors connector)
Connector: sap_success_factors_loves_prod -> Snowflake database FIVETRAN_PROD, schema SAP_SUCCESS_FACTORS_LOVES_PROD Related ticket: 401921. That ticket has the same root cause. It covers JobApplicationStatusAuditTrail on our test connector. Date: 2026-11-02
Summary
The connector lands SAP SuccessFactors OData navigation properties as __deferred placeholders, not as values. We need specific navigation properties expanded with $expand. We also need each related entity's key flattened into a scalar column.
This request lists every table and column our current reporting needs. We are not asking for all navigation properties to be expanded.
The ask
For each navigation property listed below:
- Request it with
$expand. - Return only the related entity's key, using
$select(for exampleexternalCode) to keep the payload small. - Land that key as a scalar column in the destination, beside the existing navigation column.
For example, FODepartment would be requested as follows:
GET /odata/v2/FODepartment
?$expand=parentNav
&$select=externalCode,startDate,parentNav/externalCode
The result would land as a scalar column such as parent_external_code.
Please backfill every expanded column across the table's full history. Do this with a historical re-sync when the expansion is enabled or inform the customer they need to manually resync the table themselves. A key that lands only on rows synced after the change leaves the history unusable. That is what happened on JOB_APPLICATION_STATUS_AUDIT_TRAIL (see below).
The connector has done this before, more than once. Two examples on our own connector:
-
JOB_APPLICATION.CUSTOM_JOB_APP_STATUSarrives hydrated on every row. -
JOB_APPLICATION_STATUS_AUDIT_TRAILgained three scalar keys from expanded navigation properties, starting with syncs on 2026-10-15. The keys areJOB_APPLICATION_ID,JOB_APP_STATUS_IDandJOB_APP_STATUS_SET_ID.
So this request asks for a pattern that already works in the connector, applied to more properties.
What lands today
The table below shows every column in this request, measured on the production connector on 2026-11-02. "Pure stub" means the value's only key is __deferred.
| Table | Column | Rows | Pure-stub rows |
|---|---|---|---|
FO_DEPARTMENT |
CUSTOM_PARENT_NAV |
1,330 | 1,330 |
FO_DEPARTMENT |
CUSTOM_CUST_TO_DIVISION |
1,330 | 1,330 |
FO_DEPARTMENT |
CUSTOM_DIVISION_FLX_NAV |
1,330 | 1,330 |
FO_DIVISION |
CUSTOM_PARENT_NAV |
444 | 444 |
FO_DIVISION |
CUSTOM_CUST_DIVISION |
444 | 444 |
FO_COST_CENTER |
CUSTOM_PARENT_NAV |
6,868 | 6,868 |
POSITION |
CUSTOM_JOB_CODE_NAV |
100,732 | 100,730 (the other 2 are null) |
JOB_REQUISITION |
All 11 org columns listed under priority 1 | 173,479 each | 173,479 each |
Priority 1 - organisational assignment on JobRequisition
We need the organisation each requisition was raised for. Every one of these columns is a placeholder on all 173,479 rows today.
| Destination column | SuccessFactors navigation property | Key we need |
|---|---|---|
CUSTOM_COST_CENTER_OBJ |
costCenter_obj |
cost center external code |
CUSTOM_DEPARTMENT_OBJ |
department_obj |
department external code |
CUSTOM_DIVISION_OBJ |
division_obj |
division external code |
CUSTOM_CUST_DIVISION_OBJ |
cust_division_obj |
division external code |
CUSTOM_BUSINESS_UNIT_OBJ |
businessUnit_obj |
business unit external code |
CUSTOM_LEGAL_ENTITY_OBJ |
legalEntity_obj |
legal entity (company) external code |
CUSTOM_LOCATION_OBJ |
location_obj |
location external code |
CUSTOM_LOCATION_OBJLIST |
location_objlist |
location external codes (a list) |
CUSTOM_JOB_CLASSIFICATION |
JobClassification |
job code |
CUSTOM_REQ_COMPANY_NAME |
req_CompanyName |
company external code |
CUSTOM_STD_POSITION_OBJLIST |
std_position_objlist |
position codes (a list) |
We do not need hiringManager expanded. JOB_REQUISITION_OPERATOR already gives us the hiring manager's user id.
A related type defect: JOB_REQUISITION.COST_CENTER_ID and JOB_REQUISITION.POSTALCODE are TEXT columns. On all 173,479 rows they hold the __deferred placeholder text, not a value. Please check whether these are navigation properties landing in scalar-typed columns. If they are, please expand them in the same way.
Priority 2 - organisational hierarchy on the foundation objects
We need these parent links to roll departments up to divisions, divisions up to business units, and cost centers up to their parents. Every one is a placeholder on every row today.
| Destination table | Destination column | Key we need |
|---|---|---|
FO_DEPARTMENT |
CUSTOM_PARENT_NAV |
parent department external code |
FO_DEPARTMENT |
CUSTOM_CUST_TO_DIVISION |
division external code |
FO_DEPARTMENT |
CUSTOM_DIVISION_FLX_NAV |
division external code |
FO_DIVISION |
CUSTOM_PARENT_NAV |
parent (business unit) external code |
FO_DIVISION |
CUSTOM_CUST_DIVISION |
division external code |
FO_COST_CENTER |
CUSTOM_PARENT_NAV |
parent cost center external code |
The scalar half of each of these pairs is absent, for example a plain parent column. In 107 other scalar-and-navigation pairs in this schema, the scalar half lands correctly. So the only route to these values is the navigation property.
Priority 3 - job code to job function
POSITION.JOB_CODE lands as a scalar. We cannot map it to a job function, because the job classification object (FOJobCode) is not available in the connector. We would accept either of two fixes:
-
Option A: make
FOJobCode(thefo_job_codetable) available to sync, with itsjobFunctionfield. Support has already acknowledged thatfo_job_codeis missing from the supported-schema documentation. -
Option B: expand
POSITION.CUSTOM_JOB_CODE_NAV(jobCodeNav) and returnjobCodeNav/jobFunctionas a scalar column.
Ticket 401921 follow-up - backfill JOB_APPLICATION_STATUS_AUDIT_TRAIL
Thank you for expanding jobApplication and jobAppStatus on this table. The keys you added are correct. The history was not backfilled, though, so the table is still 99.3% unusable.
The keys are correct where they exist
These figures cover the rows that carry keys, read on the production connector on 2026-11-02.
| Check | Result |
|---|---|
Rows with JOB_APPLICATION_ID
|
108,175 |
Rows with JOB_APP_STATUS_ID and JOB_APP_STATUS_SET_ID
|
108,177 |
| Keys holding placeholder text | 0 |
| Applications covered | 47,602 |
Applications that match a JOB_APPLICATION row |
47,600. The two that don't are application ids 4916065 and 4930579. |
Each application's latest audit status equals its current status on JOB_APPLICATION
|
99.97% (47,587 of 47,600) |
| Distinct status ids | 57. One of them matches no status seen on JOB_APPLICATION. |
The history has no keys
| Check | Result |
|---|---|
| Total rows | 16,532,602 |
Rows with null keys and a __deferred placeholder in CUSTOM_JOB_APPLICATION and CUSTOM_JOB_APP_STATUS
|
16,420,225 (99.3%) |
| First sync date that carries keys | 2026-10-15 |
| Keyed rows among events created May to September 2026 | 0 |
| Keyed rows among events created in October 2026 | 96,409 of 175,527 |
| Keyed rows among events created in November 2026 | 11,766 of 11,766 |
Keys appear only on rows synced since 2026-10-15. Rows synced before that date were never re-landed. The audit trail goes back to 2014-05-08, so almost all of the funnel history is still unattributable.
Two details make us want your confirmation before a re-sync:
- No old event has ever been re-read with the expansion. Every keyed row was created on or after 2026-10-15. So we have no evidence yet that the API returns the related application for older events, including events from 2014.
- The expansion was not applied consistently at first. 6,091 rows synced between 2026-10-15 and 2026-10-26 still arrived keyless. Those events were created between 2026-10-14 and 2026-10-25. Every row synced from 2026-10-27 onward carries keys.
What we are doing: we are running a historical re-sync of JOB_APPLICATION_STATUS_AUDIT_TRAIL ourselves.
The ask:
- Please confirm that the re-sync requests every row with the expanded
jobApplicationandjobAppStatusproperties. - If SAP returns no related application for some older events, please tell us how those rows will land.
- Please tell us what changed between 2026-10-15 and 2026-10-26, when 6,091 newly synced rows still arrived without keys.
We will report the post-re-sync key coverage back on this ticket. We list it beside the new expansions because one fix to navigation-property expansion, with a backfill, covers all of these tables.
Two smaller observations on the same table
-
LAST_MODIFIED_DATE_TIMEcarries no time of day on any row. Every value is midnight.CREATED_DATE_TIMEdoes carry a time, on 16,528,217 rows. Please check whether the time part is being dropped fromlastModifiedDateTime. -
REV_TYPEis null on every row. SAP's API Reference Guide listsrevTypeas a scalar property of this entity.
How we measured
All figures were read from the production destination (FIVETRAN_PROD.SAP_SUCCESS_FACTORS_LOVES_PROD) on 2026-11-02. We used read-only aggregate queries over every row, not samples. A value counts as a placeholder when its JSON object has exactly one key, __deferred. We can share the queries.
-
Official comment
Hi Andy,
Thank you for your detailed feature request regarding the expansion of OData navigation properties in the SAP SuccessFactors connector. Currently, these feature enhancements are not on our immediate roadmap. However, we have added this to our active backlog and are reviewing how to expand the specific navigation properties you listed. We encourage you to upvote this request on our feature request portal, as customer demand help prioritize feature enhancements. We will keep you updated on this thread as we make progress.
Thank you,
Sanjeevv Maniram.
Please sign in to leave a comment.
Comments
1 comment