Workday HCM to SAP S/4HANA Finance Integration Playbook

Type: ERP Integration Systems: Workday HCM (2025R2), SAP S/4HANA Finance (2023+), SAP Integration Suite Confidence: 0.84 Sources: 7 Verified: 2026-03-07 Freshness: volatile

TL;DR

System Profile

This integration playbook covers the notoriously complex pattern of connecting Workday HCM (system of record for employee master data, compensation, and organizational structures) with SAP S/4HANA Finance (system of record for general ledger, cost centers, profit centers, and financial reporting). A middleware layer — typically SAP Integration Suite (BTP) or MuleSoft Anypoint — handles orchestration, transformation, error handling, and monitoring. The pattern applies to both SAP S/4HANA Cloud and on-premise deployments, though API surfaces differ significantly between them. [src1]

This playbook does NOT cover SAP SuccessFactors Employee Central (which has its own native SAP integration patterns), SAP ECC 6.0 legacy (which uses different BAPIs/IDocs), or Workday Financial Management (which would eliminate the need for SAP Finance entirely). [src2]

SystemRoleAPI SurfaceDirection
Workday HCM (2025R2)Employee master — source of truth for workers, compensation, orgs, benefitsREST API, SOAP (WWS v42.1), RaaS, WQL, PECIOutbound (publishes changes)
SAP S/4HANA Finance (2023+)Financial master — GL, cost centers, profit centers, journalsOData v4, BAPI (RFC), IDoc, SOAP (Journal Entry Post)Inbound (consumes employee cost data)
Middleware (SAP IS / MuleSoft)Orchestration, transformation, error handling, monitoringPre-built iFlows / Anypoint connectorsOrchestrator

API Surfaces & Capabilities

API SurfaceSystemProtocolBest ForMax Records/RequestRate LimitReal-time?Bulk?
REST APIWorkdayHTTPS/JSONIndividual worker CRUD, custom objects, WQL queriesPaginated (100-200/page)~60 req/min per resourceYesNo
SOAP (WWS)WorkdayHTTPS/XMLFull worker data retrieval, Get_Workers, Put operationsPaginated (100-500/page)~1,000 req/min per tenantYesLimited
RaaSWorkdayHTTPS/XML or CSVBulk data extraction via custom reports2 GB per reportNo strict rate limit (10 min timeout)NoYes
PECIWorkdayHTTPS/XMLDelta extraction of payroll-relevant changesAll changes in pay period windowPer pay group executionNoYes
WQLWorkdayHTTPS/JSONAd-hoc queries, cost center lookups, org dataPaginatedShared with REST limitsYesNo
OData v4SAP S/4HANAHTTPS/JSONCost center read, journal entry read, master data query1,000 per page (server-driven)200 concurrent connectionsYesNo
BAPI (RFC)SAP S/4HANARFC/XMLCost center create/update, GL account master1 per call (composable)Dialog work process limitYesNo
SOAP (Journal Entry Post)SAP S/4HANAHTTPS/XMLPayroll journal posting (sync + async)1,000 line items (sync), unlimited (async)Queued processingSync: YesAsync: Yes
IDocSAP S/4HANAEDI/XMLCost center hierarchy, org structure mass updates1 per IDoc (bundleable)Async queueNoYes

Rate Limits & Quotas

Per-Request Limits

Limit TypeValueApplies ToNotes
REST pagination page size100-200 recordsWorkday REST APIDefault 20; max varies by resource
SOAP Get_Workers page size100-500 recordsWorkday WWSSet via Count element in request
RaaS report size2 GB max outputWorkday RaaSReports exceeding this fail silently
OData page size1,000 recordsSAP S/4HANA OData v4Server-driven pagination ($skiptoken)
Journal Entry line items1,000 per documentSAP SOAP (synchronous)Use async for larger documents
PECI extract windowCurrent + 2 prior pay periodsWorkday PECIConfigurable per pay group

Rolling / Daily Limits

Limit TypeValueWindowSystem
REST requests per resource~60Per minuteWorkday REST API
SOAP requests per tenant~1,000Per minuteWorkday WWS
Concurrent API sessions5-10 (tenant-specific)ConcurrentWorkday (all APIs)
OData concurrent connections200Per tenantSAP S/4HANA Cloud
RFC dialog work processesConfigurable (typically 20-80)ConcurrentSAP S/4HANA On-Premise
Background job slotsConfigurableConcurrentSAP (BAPI/IDoc async)

Transaction / Governor Limits

Limit TypePer-Transaction ValueNotes
Workday integration event timeout10 minutes (RaaS), 5 minutes (REST/SOAP per request)Exceeding causes silent timeout; no partial results for RaaS
SAP dialog step time limit600 seconds (default)Configurable via rdisp/max_wprun_time; exceeded = ABAP dump
SAP update task (V2)5 seconds (recommended)Long-running V2 updates block subsequent document posting
Workday EIB file size5 MB per uploadEnterprise Interface Builder file imports

Authentication

FlowSystemUse WhenToken LifetimeRefresh?Notes
ISU + WS-SecurityWorkday SOAPServer-to-server SOAP callsSession-basedN/ACreate dedicated ISU per integration; do not reuse
OAuth 2.0 (Authorization Code)Workday RESTREST API calls, WQLAccess: 1h, Refresh: non-expiringYes (non-expiring refresh tokens)Register API client with "Non-Expiring Refresh Tokens" enabled
OAuth 2.0 (Client Credentials)SAP S/4HANA CloudOData, SOAP calls to cloudAccess: 12h (configurable)YesRegistered via SAP BTP cockpit
X.509 CertificateSAP S/4HANA CloudMutual TLS for BTP Integration SuiteCertificate validity periodN/ARecommended for production SAP IS iFlows
SAP Logon (Basic Auth over RFC)SAP S/4HANA On-PremBAPI/RFC calls from middlewareSession-basedN/ARequires RFC-type communication user (dialog-free)

Authentication Gotchas

Constraints

Integration Pattern Decision Tree

START — Integrating Workday HCM with SAP S/4HANA Finance
├── What data flows are needed?
│   ├── Employee Master Sync (hire/change/term)
│   │   ├── Volume < 500 changes/day?
│   │   │   ├── YES → Workday REST API (Get_Workers delta) → middleware → SAP BAPI or OData
│   │   │   └── NO → Workday RaaS (scheduled report) → middleware → SAP IDoc batch
│   │   └── Need real-time (< 5 min latency)?
│   │       ├── YES → Workday Integration Event → middleware webhook → SAP OData
│   │       └── NO → Scheduled batch via RaaS (recommended for most cases)
│   ├── Cost Center / Org Hierarchy Sync
│   │   ├── Source of truth = SAP?
│   │   │   └── YES → SAP OData read → middleware → Workday SOAP Put_Cost_Center
│   │   ├── Source of truth = Workday?
│   │   │   └── YES → Workday RaaS → middleware → SAP BAPI_COSTCENTER_CREATEMULTIPLE
│   │   └── Bidirectional?
│   │       └── Design conflict resolution FIRST — pick one master, replicate to other
│   ├── Payroll Journal Posting to GL
│   │   ├── Using Workday Payroll?
│   │   │   └── YES → Workday PECI → middleware → SAP Journal Entry Post (Async SOAP)
│   │   ├── Using SAP Payroll (hybrid)?
│   │   │   └── YES → Workday PECI → SAP Integration Suite → SAP Payroll (native)
│   │   └── Using third-party payroll?
│   │       └── Payroll → middleware → SAP Journal Entry Post (separate integration)
│   └── Benefits/Compensation to GL
│       └── Workday RaaS (compensation report) → middleware → SAP cost allocation journal
├── Which middleware?
│   ├── SAP Integration Suite → pre-built Workday iFlows, native SAP connectivity
│   ├── MuleSoft → Workday Connector v16.x + SAP Connector v5.x
│   └── Boomi → pre-built Workday-SAP process templates
└── Error strategy?
    ├── Financial data (journals) → zero-loss: idempotency + DLQ + reconciliation
    └── Master data (employee sync) → retry 3x with backoff, then alert

Quick Reference

Process Flow — Full Integration Scope

StepSource SystemActionTarget SystemData ObjectsFrequencyFailure Handling
1SAP S/4HANACost center/org hierarchy export via ODataWorkday HCMCost Center, Profit Center, Company CodeDaily (or on-change)Retry 3x, alert on 4th failure
2Workday HCMEmployee master delta via RaaS or RESTSAP S/4HANAWorker ID, Name, Cost Center assignment, Position, Job ProfileEvery 4-6 hoursRetry 3x, quarantine failed records
3Workday HCMOrg assignment changes via RaaSSAP S/4HANASupervisory Org → Cost Center mappingDailyManual review for unmapped orgs
4Workday HCMPECI extract: payroll-relevant changesMiddlewareCompensation, deductions, pay component changesPer payroll cycleHold for next cycle if cut-off missed
5MiddlewareTransform PECI to SAP journal formatSAP S/4HANAJournal Entry (company code, GL, cost center, amount)Per payroll cycleDead letter queue + finance team alert
6Workday HCMBenefits cost allocation via RaaSSAP S/4HANABenefit plan costs → GL cost allocationMonthlyReconciliation report
7SAP S/4HANAPosting confirmation (document number)Middleware logAccounting document ID, statusPer postingLog for audit trail

Step-by-Step Integration Guide

1. Establish Workday ISU and API Client Registration

Create a dedicated Integration System User (ISU) in Workday and register an API client for OAuth 2.0 access. The ISU must have security group access to the integration domain policies covering Worker Data, Compensation, and Organization Data. [src3]

# Step 1: In Workday, search "Create Integration System User"
# Create ISU: WD_SAP_INTEGRATION_USER
# Assign to Integration System Security Group with policies:
#   - Worker Data: Get (Public + Private)
#   - Compensation: Get
#   - Organization: Get
#   - Payroll Interface: Get

# Step 2: Register API Client
# Search "Register API Client for Integrations"
# Client Name: SAP_Finance_Integration
# Enable: Non-Expiring Refresh Tokens
# Scope: Integration (System scope)
# Note the Client ID and Client Secret

# Step 3: Generate initial OAuth tokens
curl -X POST "https://{tenant}.workday.com/ccx/oauth2/{tenant}/token" \
  -d "grant_type=authorization_code" \
  -d "client_id={CLIENT_ID}" \
  -d "client_secret={CLIENT_SECRET}" \
  -d "code={AUTHORIZATION_CODE}" \
  -d "redirect_uri={REDIRECT_URI}"

Verify: curl -H "Authorization: Bearer {ACCESS_TOKEN}" "https://{tenant}.workday.com/ccx/api/v1/{tenant}/workers?limit=1" → expected: JSON with one worker record and total count.

2. Configure SAP Communication Arrangement (S/4HANA Cloud)

For SAP S/4HANA Cloud, create a communication arrangement in the Fiori launchpad to expose the Journal Entry Post and Cost Center APIs to the middleware. [src7]

# In SAP S/4HANA Cloud Fiori Launchpad:
# 1. Communication Management → Communication Arrangements → New
# 2. Select Scenario: SAP_COM_0002 (Business Partner Integration)
#    or SAP_COM_0009 (Journal Entry Integration)
# 3. Create Communication System: WORKDAY_MIDDLEWARE
# 4. Authentication: OAuth 2.0 (Client Credentials)
# 5. Assign Communication User with authorization: SAP_FI_API_JOURNAL_ENTRY

# Test the SAP OData endpoint:
curl -X GET "https://{sap-host}/sap/opu/odata4/sap/api_costcenter/srvd_a2x/sap/costcenter/0001/CostCenter" \
  -H "Authorization: Bearer {SAP_TOKEN}" \
  -H "Accept: application/json"

Verify: Response contains value array with cost center objects including CostCenter, CostCenterName, ControllingArea.

3. Build Employee Master Delta Extraction (Workday → SAP)

Use Workday RaaS for scheduled batch extraction or REST API for near-real-time delta. The RaaS approach is recommended for >1,000 employees. [src3, src6]

<!-- Workday SOAP: Get_Workers with effective date filter -->
<env:Envelope xmlns:env="http://schemas.xmlsoap.org/soap/envelope/"
              xmlns:wd="urn:com.workday/bsvc">
  <env:Body>
    <wd:Get_Workers_Request wd:version="v42.1">
      <wd:Request_Criteria>
        <wd:Transaction_Log_Criteria_Data>
          <wd:Transaction_Date_Range_Data>
            <wd:Updated_From>2026-03-06T00:00:00Z</wd:Updated_From>
            <wd:Updated_Through>2026-03-07T00:00:00Z</wd:Updated_Through>
          </wd:Transaction_Date_Range_Data>
        </wd:Transaction_Log_Criteria_Data>
      </wd:Request_Criteria>
      <wd:Response_Group>
        <wd:Include_Personal_Information>true</wd:Include_Personal_Information>
        <wd:Include_Employment_Information>true</wd:Include_Employment_Information>
        <wd:Include_Organizations>true</wd:Include_Organizations>
        <wd:Include_Compensation>true</wd:Include_Compensation>
      </wd:Response_Group>
      <wd:Response_Filter>
        <wd:Count>200</wd:Count>
        <wd:Page>1</wd:Page>
      </wd:Response_Filter>
    </wd:Get_Workers_Request>
  </env:Body>
</env:Envelope>

Verify: Response contains <wd:Response_Results> with <wd:Total_Results> matching expected delta count.

4. Transform and Post Payroll Journal to SAP

Extract payroll results from Workday via PECI or RaaS, transform pay components to SAP GL accounts and cost centers, and post via SAP Journal Entry SOAP service. [src4, src6]

<!-- SAP S/4HANA: Journal Entry Post (Synchronous SOAP) -->
<soapenv:Envelope xmlns:soapenv="http://schemas.xmlsoap.org/soap/envelope/"
                  xmlns:jep="http://sap.com/xi/SAPSCORE/SBOP/JournalEntryBulkCreateRequest">
  <soapenv:Body>
    <jep:JournalEntryBulkCreateRequest>
      <MessageHeader>
        <ID>WD-PAY-2026-03-01-001</ID>
      </MessageHeader>
      <JournalEntryCreateRequest>
        <JournalEntry>
          <CompanyCode>1000</CompanyCode>
          <PostingDate>2026-03-01</PostingDate>
          <DocumentHeaderText>Workday Payroll Mar 2026</DocumentHeaderText>
          <Item>
            <GLAccount>621000</GLAccount>
            <AmountInTransactionCurrency currencyCode="USD">45000.00</AmountInTransactionCurrency>
            <DebitCreditCode>S</DebitCreditCode>
            <CostCenter>CC-1001</CostCenter>
            <DocumentItemText>Salary Expense - Engineering</DocumentItemText>
          </Item>
          <Item>
            <GLAccount>211000</GLAccount>
            <AmountInTransactionCurrency currencyCode="USD">45000.00</AmountInTransactionCurrency>
            <DebitCreditCode>H</DebitCreditCode>
            <DocumentItemText>Payroll Clearing</DocumentItemText>
          </Item>
        </JournalEntry>
      </JournalEntryCreateRequest>
    </jep:JournalEntryBulkCreateRequest>
  </soapenv:Body>
</soapenv:Envelope>

Verify: Response contains <AccountingDocument> with SAP document number and <Status> = Posted.

Code Examples

Python: Extract Workday Workers Delta via REST API

# Input:  Workday tenant URL, OAuth token, date range
# Output: List of changed worker records with org assignments

import requests
from datetime import datetime, timedelta

WORKDAY_BASE = "https://{tenant}.workday.com/ccx/api/v1/{tenant}"
TOKEN = "{OAUTH_ACCESS_TOKEN}"

def get_worker_deltas(since_hours=24, page_size=100):
    """Extract workers changed in the last N hours."""
    headers = {"Authorization": f"Bearer {TOKEN}", "Accept": "application/json"}
    workers = []
    offset = 0

    while True:
        resp = requests.get(
            f"{WORKDAY_BASE}/workers",
            headers=headers,
            params={"limit": page_size, "offset": offset},
            timeout=30
        )
        if resp.status_code == 429:  # Rate limited
            import time
            retry_after = int(resp.headers.get("Retry-After", 60))
            time.sleep(retry_after)
            continue
        resp.raise_for_status()
        data = resp.json()
        workers.extend(data.get("data", []))
        if len(data.get("data", [])) < page_size:
            break
        offset += page_size

    return workers

Python: Post Payroll Journal to SAP S/4HANA via OData

# Input:  SAP S/4HANA URL, OAuth token, journal entry payload
# Output: SAP accounting document number

import requests

SAP_BASE = "https://{sap-host}/sap/opu/odata4/sap/api_journalentryitembasic/srvd_a2x/sap/journalentryitembasic/0001"
SAP_TOKEN = "{SAP_OAUTH_TOKEN}"

def post_journal_entry(company_code, entries):
    """Post payroll journal entry to SAP S/4HANA."""
    headers = {
        "Authorization": f"Bearer {SAP_TOKEN}",
        "Content-Type": "application/json",
        "Accept": "application/json",
        "X-CSRF-Token": "Fetch"  # Required for write operations
    }
    # Step 1: Fetch CSRF token
    csrf_resp = requests.get(SAP_BASE, headers=headers, timeout=30)
    csrf_token = csrf_resp.headers.get("X-CSRF-Token")
    headers["X-CSRF-Token"] = csrf_token

    # Step 2: Post journal
    payload = {
        "CompanyCode": company_code,
        "DocumentDate": "2026-03-01",
        "PostingDate": "2026-03-01",
        "DocumentHeaderText": "WD Payroll",
        "to_Item": entries  # List of line items
    }
    resp = requests.post(SAP_BASE, json=payload, headers=headers, timeout=60)
    resp.raise_for_status()
    return resp.json().get("AccountingDocument")

cURL: Test Workday RaaS Report Extraction

# Input:  Workday RaaS URL with ISU credentials
# Output: CSV or XML report data

# Fetch a custom report via RaaS (CSV format)
curl -u "ISU_USERNAME:ISU_PASSWORD" \
  "https://{tenant}.workday.com/ccx/service/customreport2/{tenant}/{report_owner}/{report_name}?format=csv&Employee_Status=Active" \
  -H "Accept: text/csv" \
  -o workday_active_workers.csv

# Verify output
head -5 workday_active_workers.csv
# Expected: CSV headers: Employee_ID,Legal_Name,Cost_Center,Supervisory_Org,...

Data Mapping

Field Mapping Reference

Source Field (Workday)Target Field (SAP S/4HANA)TypeTransformGotcha
Worker > Employee_IDBusiness Partner > BPNumber or Personnel NumberStringCross-reference table (WD ID → SAP Personnel No.)Workday IDs can be alphanumeric; SAP personnel numbers are 8-digit numeric
Worker > Legal_Name > Last_NameBusiness Partner > LastNameStringDirect (truncate to 40 chars)SAP max 40 chars; Workday allows 100+
Worker > Organization > Cost_Center_ReferenceControlling > CostCenterStringLookup: WD cost center ID → SAP cost center + controlling areaWorkday cost center IDs ≠ SAP cost center codes; mapping table required
Worker > Compensation > Total_Base_PayGL Posting > AmountInTransactionCurrencyDecimalSum by cost center for journal aggregationWorkday stores annualized; SAP journals need per-period amounts
Worker > Organization > Company_ReferenceCompany CodeStringLookup: WD company → SAP company code (4-char)Must map before any GL posting; unmapped = rejected
PECI > Pay_ComponentGL AccountStringMapping table: WD pay component code → SAP GL accountMany-to-many possible; one WD component may split across SAP GL accounts
Worker > Hire_Date / Termination_DateEffective date on SAP recordsDateDirect (YYYY-MM-DD)Timezone differences: Workday stores in tenant TZ; SAP uses server TZ
Worker > Position > Job_ProfileSAP Position / Job KeyStringCross-reference mappingJob profiles are customer-defined in both systems; no standard mapping
Worker > Currency_CodeCurrency key on journalString (ISO 4217)DirectBoth use ISO 4217 — but exchange rates may differ between systems

Data Type Gotchas

Error Handling & Failure Points

Common Error Codes

CodeSystemMeaningCauseResolution
429Workday RESTRate limit exceededExceeded ~60 req/min per resourceExponential backoff: wait Retry-After header value, typically 60s
SOAP Fault: INVALID_CREDENTIALSWorkday SOAPISU authentication failedPassword expired or ISU disabledCheck ISU status; passwords may auto-expire per tenant policy
HTTP 403SAP S/4HANA CloudAuthorization failedMissing scope in Communication ArrangementVerify Communication User has required authorization objects
F5 066SAP FIFiscal period closedPosting date falls in a closed fiscal periodUse next open period, or request finance to reopen period for retroactive posting
KI 235SAP COCost center does not existWorkday cost center not yet created in SAPRun cost center sync before employee/journal sync; add dependency check
BAPI_ERROR: AG 605SAP BAPICompany code invalidWorkday company mapping returned invalid SAP company codeValidate mapping table; ensure all WD companies map to valid SAP company codes
Timeout (no response)Workday RaaSReport execution exceeded 10 minReport too large or complexAdd filters (date range, org scope) to reduce report size; split into segments

Failure Points in Production

Anti-Patterns

Wrong: Real-time sync for payroll journal data

# BAD -- posting individual employee salary lines to SAP in real-time
for employee in workday_payroll_results:
    post_to_sap(employee.salary, employee.cost_center)
    # 10,000 API calls for 10,000 employees
    # Hits SAP rate limits, creates 10,000 individual journal documents
    # Finance team cannot reconcile 10,000 documents per pay period

Correct: Batch aggregation by cost center, then single journal document

# GOOD -- aggregate payroll results by cost center and GL account
from collections import defaultdict

aggregated = defaultdict(float)
for employee in workday_payroll_results:
    key = (employee.company_code, employee.gl_account, employee.cost_center)
    aggregated[key] += employee.amount

journal_lines = [
    {"GLAccount": gl, "CostCenter": cc, "CompanyCode": co, "Amount": amt}
    for (co, gl, cc), amt in aggregated.items()
]
post_journal_to_sap(journal_lines)  # 1 API call, 1 journal document

Wrong: Ignoring effective-dated records (snapshot approach)

# BAD -- extracting all workers and comparing with previous snapshot
current_workers = get_all_workers()  # 50,000 API calls for 50,000 employees
previous_workers = load_previous_snapshot()
changes = diff(current_workers, previous_workers)
# Breaks Workday rate limits; misses retroactive changes; takes 14 hours

Correct: Delta extraction using transaction log date filter

# GOOD -- extract only changes since last run using effective date range
changes = get_workers_delta(
    updated_from="2026-03-06T00:00:00Z",
    updated_through="2026-03-07T00:00:00Z"
)
# 50 changes instead of 50,000 full records; completes in 2 minutes
# Catches retroactive changes via Workday's transaction log

Wrong: Mapping Workday supervisory orgs directly to SAP cost centers by name

# BAD -- matching by org name string
sap_cost_center = find_by_name(workday_supervisory_org.name)
# "Engineering - Platform" in Workday != "Platform Engineering" in SAP
# Name changes in either system silently break the integration

Correct: Cross-reference mapping table with stable IDs

# GOOD -- use integration-managed mapping table with stable IDs
mapping = load_mapping_table()  # {WD_Cost_Center_Ref_ID: SAP_Cost_Center_Code}
sap_cost_center = mapping.get(workday_worker.cost_center_ref_id)
if not sap_cost_center:
    send_to_dead_letter_queue(workday_worker, "UNMAPPED_COST_CENTER")
    alert_integration_admin(workday_worker.cost_center_ref_id)

Common Pitfalls

Diagnostic Commands

# Check Workday API health and ISU permissions
curl -u "ISU_USER:ISU_PASSWORD" \
  "https://{tenant}.workday.com/ccx/service/{tenant}/Human_Resources/v42.1" \
  -H "Accept: text/xml"
# Expected: WSDL document (confirms ISU credentials and SOAP access)

# Test Workday REST API with OAuth token
curl -H "Authorization: Bearer {TOKEN}" \
  "https://{tenant}.workday.com/ccx/api/v1/{tenant}/workers?limit=1"
# Expected: JSON with total count and 1 worker record

# Test Workday RaaS custom report
curl -u "ISU_USER:ISU_PASSWORD" \
  "https://{tenant}.workday.com/ccx/service/customreport2/{tenant}/{owner}/{report}?format=csv" \
  -o test_report.csv && wc -l test_report.csv
# Expected: CSV file with header row + data rows

# Test SAP S/4HANA OData cost center read
curl -H "Authorization: Bearer {SAP_TOKEN}" \
  "https://{sap-host}/sap/opu/odata4/sap/api_costcenter/srvd_a2x/sap/costcenter/0001/CostCenter?\$top=5"
# Expected: JSON with 5 cost center records

# Test SAP CSRF token fetch (required before write operations)
curl -v -H "Authorization: Bearer {SAP_TOKEN}" \
  -H "X-CSRF-Token: Fetch" \
  "https://{sap-host}/sap/opu/odata4/sap/api_journalentryitembasic/srvd_a2x/sap/journalentryitembasic/0001" \
  2>&1 | grep "x-csrf-token"
# Expected: x-csrf-token header with token value (not "Required")

Version History & Compatibility

ComponentVersionRelease DateStatusBreaking Changes
Workday REST APIv1 (2025R2)2025-09CurrentREST is stable; WQL added in 2024R1
Workday SOAP (WWS)v42.12025-09CurrentSeveral Worker endpoints deprecated from SOAP-only in 2025R1
Workday PECI2025R22025-09CurrentAdded support for custom pay component grouping
SAP S/4HANA Cloud OData24082024-08CurrentJournal Entry API v2 (OData v4) replaced v1; BTP IS mandatory
SAP S/4HANA On-Prem OData2023 FPS022024-01SupportedCost Center OData API moved from v2 to v4
SAP BAPI (RFC)StableN/ASupportedBAPI_ACC_DOCUMENT_POST still supported; not deprecated
SAP IS Workday Adapter2025-Q32025-07CurrentUpgraded OAuth 2.0 support; PECI iFlow templates added
MuleSoft Workday Connectorv16.42025-10CurrentAdded WQL support; minimum Mule Runtime 4.3
MuleSoft SAP Connectorv5.82025-08CurrentAdded S/4HANA Cloud OData v4 support

When to Use / When Not to Use

Use WhenDon't Use WhenUse Instead
Workday is the HCM system of record and SAP S/4HANA is the finance/controlling systemBoth HR and Finance are in SAP (SuccessFactors + S/4HANA)Native SAP EC-Payroll integration via SAP Integration Suite
Need automated payroll journal posting from Workday payroll results to SAP GLUsing Workday Financial Management (no SAP Finance)Workday native reporting and GL posting
Complex cost allocation: multiple company codes, cost centers, profit centers across SAPSimple single-entity payroll with <500 employeesFile-based CSV upload to SAP (manual or scheduled)
Regulatory requirements demand audit trail for cross-system data flowSAP ECC 6.0 (not S/4HANA) is the targetAdapt BAPI/IDoc patterns for ECC; this playbook assumes S/4HANA APIs
Enterprise with >5,000 employees and multi-country payrollWorkday Adaptive Planning (not HCM) to SAP integrationSeparate planning integration playbook

Cross-System Comparison

CapabilityWorkday HCMSAP S/4HANA FinanceNotes
API StyleREST + SOAP + RaaSOData v4 + BAPI + IDoc + SOAPWorkday moving to REST; SAP moving to OData v4
Rate Limits~60 REST/min, ~1,000 SOAP/min200 concurrent OData connectionsWorkday more restrictive for real-time
Bulk ExportRaaS (2 GB/report)OData paging, BAPI batch, IDocRaaS is Workday's strength for bulk
Bulk ImportEIB (5 MB/file), SOAP Put operationsBAPI batch, IDoc, SOAP Journal PostSAP handles larger batch volumes
Effective DatingNative — all records are effective-datedTransaction-date-based, fiscal period controlsFundamental architectural difference
Org StructureSingle unified hierarchy (supervisory orgs)Multiple hierarchies (cost center, profit center, HR org unit, company code)1:many mapping required
AuthISU + OAuth 2.0OAuth 2.0, X.509, SAP LogonBoth support OAuth; SAP adds cert-based
SandboxTenant refresh (full copy)Quality/Development clientsBoth have realistic test environments
Change NotificationIntegration Events, Workday Business ProcessSAP Event Mesh, ABAP triggersNeither has native cross-system CDC

Important Caveats

Related Units