---
# === IDENTITY ===
id: business/erp-integration/oracle-hcm-cloud-api/2026
canonical_question: "What are the Oracle HCM Cloud API capabilities - REST, HDL, HCM Extracts, payroll, and worker management?"
aliases:
  - "Oracle Fusion Cloud HCM REST API endpoints and rate limits"
  - "Oracle HCM Data Loader (HDL) capabilities and file size limits"
  - "Oracle Cloud HCM worker API vs HDL for bulk employee imports"
  - "Oracle HCM Extracts and BI Publisher for outbound HR data"
entity_type: erp_integration
domain: business > erp-integration > oracle-hcm-cloud-api
region: global
jurisdiction: global
temporal_scope: 2024-2026

# === SYSTEM PROFILE ===
systems:
  - name: "Oracle Fusion Cloud HCM"
    vendor: "Oracle"
    version: "24B (REST API v11.13.18.05)"
    edition: "Enterprise"
    deployment: cloud
    api_surface: "REST, HDL, HCM Extracts, BIP, SOAP (legacy)"

# === VERIFICATION ===
last_verified: 2026-03-09
confidence: 0.85
version: 1.0
first_published: 2026-03-09

# === TEMPORAL VALIDITY ===
temporal_validity:
  status: volatile
  last_breaking_change: "24B - expanded workers REST resource with additional child objects"
  next_review: 2026-09-05
  change_sensitivity: high

# === CONSTRAINTS ===
constraints:
  - "REST API is NOT suitable for bulk operations (>500 records) — use HDL for any volume above 500 workers"
  - "HDL file size limit: 250 MB per file, 20 concurrent loader threads per pod"
  - "REST fair-use throttling: ~60 requests/second (not officially published), returns HTTP 429 when exceeded"
  - "REST pagination: 500 records max per page via limit parameter"
  - "Payroll REST APIs require separate Oracle Payroll license — they are not included in core HCM"
  - "SOAP APIs are legacy/maintenance-only — Oracle recommends REST or HDL for all new integrations"
  - "HCM Extracts are outbound-only — cannot be used for inbound data loading"

# === SKIP CONDITIONS ===
skip_this_unit_if:
  - condition: "User needs Oracle E-Business Suite HRMS APIs — on-premise, PL/SQL-based"
    use_instead: "N/A — EBS HRMS uses PL/SQL APIs, not covered here"
  - condition: "User needs Oracle Taleo recruiting APIs — separate product"
    use_instead: "N/A — Taleo has its own REST API documentation"
  - condition: "User needs Oracle Financials or SCM REST APIs — different API documentation set"
    use_instead: "business/erp-integration/oracle-financials-cloud-api/2026"

# === AGENT HINTS ===
inputs_needed:
  - key: integration_pattern
    question: "What integration pattern do you need?"
    type: choice
    options:
      - "real-time sync (individual records, <1s latency)"
      - "batch/bulk (scheduled, high volume)"
      - "event-driven (Business Events, atom feeds)"
      - "file-based (HDL dat files, HCM Extracts)"
  - key: data_volume
    question: "What's your daily data volume?"
    type: choice
    options:
      - "< 500 records/day"
      - "500-50,000 records/day"
      - "> 50,000 records/day"
  - key: direction
    question: "What's the data flow direction?"
    type: choice
    options:
      - "inbound (writing to Oracle HCM)"
      - "outbound (reading from Oracle HCM)"
      - "bidirectional sync"

# === DISTRIBUTION ===
canonical_source: "https://knowledgelib.io/business/erp-integration/oracle-hcm-cloud-api/2026"
suggested_citation: "Source: knowledgelib.io — AI Knowledge Library (verified 2026-03-09)"

# === RELATED UNITS ===
related_kos:
  depends_on: []
  related_to:
    - id: "business/erp-integration/oracle-financials-cloud-api/2026"
      label: "Oracle Financials Cloud API — complementary ERP pillar"
  solves: []
  alternative_to: []
  often_confused_with: []

# === SOURCES (6 authoritative sources) ===
sources:
  - id: src1
    title: "REST API for Oracle Fusion Cloud HCM — Workers Resource"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/human-resources/24b/farwh/Workers.html
    type: official_docs
    published: 2024-07-01
    reliability: authoritative
  - id: src2
    title: "HCM Data Loader — Loading Objects Tutorial"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/human-resources/24b/hdltu/index.html
    type: official_docs
    published: 2024-07-01
    reliability: authoritative
  - id: src3
    title: "REST API for Oracle Fusion Cloud HCM — Payroll Relationships"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/human-resources/24b/farwh/PayrollRelationships.html
    type: official_docs
    published: 2024-07-01
    reliability: authoritative
  - id: src4
    title: "HCM Extracts — Architecture and Best Practices"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/post/hcm-extract-best-practices
    type: technical_blog
    published: 2024-03-15
    reliability: high
  - id: src5
    title: "Oracle HCM Cloud Integration Best Practices"
    author: Oracle A-Team
    url: https://www.ateam-oracle.com/post/oracle-hcm-cloud-integration-best-practices
    type: technical_blog
    published: 2024-06-01
    reliability: high
  - id: src6
    title: "Oracle HCM Cloud REST API Authentication — OAuth 2.0 JWT Bearer"
    author: Oracle
    url: https://docs.oracle.com/en/cloud/saas/human-resources/24b/farwh/Authentication_and_Authorization.html
    type: official_docs
    published: 2024-07-01
    reliability: authoritative
---

# Oracle HCM Cloud API Capabilities — REST, HDL, HCM Extracts, Payroll, Workers

## TL;DR

- **Bottom line**: Oracle Fusion Cloud HCM exposes REST APIs for real-time worker management (hire, query, update) and HDL (HCM Data Loader) for bulk inbound operations. HCM Extracts and BIP handle outbound bulk data extraction. REST is limited to ~500 records per operation — anything above that volume must use HDL.
- **Key limit**: REST fair-use throttling at ~60 req/s (HTTP 429 when exceeded); HDL max 250 MB per file with 20 concurrent loader threads per pod; REST pagination capped at 500 records per page.
- **Watch out for**: Payroll REST APIs (payroll relationships, payroll results, payslips) require a separate Oracle Payroll license — they return 403 or empty results without the license, and the error message does not clearly indicate a licensing issue.
- **Best for**: REST for real-time individual worker operations (hire, terminate, transfer, query <500 records); HDL for bulk loads (new hire imports, annual compensation updates, benefits enrollment); HCM Extracts for scheduled outbound feeds to downstream systems.
- **Authentication**: OAuth 2.0 JWT Bearer flow recommended for server-to-server integrations via Oracle IDCS; Basic Auth supported but not recommended for production.

## System Profile

Oracle Fusion Cloud HCM (also branded Oracle Cloud HCM or Oracle HCM Cloud) is Oracle's SaaS human capital management suite. The REST API surface covers Core HR (workers, assignments, employment), Workforce Management, Compensation, Benefits, Talent, Learning, and Payroll (with separate license). HCM Data Loader (HDL) is the primary bulk inbound mechanism, using structured .dat files uploaded via the HCM Imports REST resource or UCM. HCM Extracts provide configurable outbound data extraction with delivery to UCM, FTP, or BI Publisher. [src1]

This card covers Oracle Fusion Cloud HCM only — not Oracle E-Business Suite HRMS (on-premise, PL/SQL APIs), Oracle Taleo (recruiting, separate SaaS), or PeopleSoft HCM (on-premise). The REST API version is 11.13.18.05, stable across quarterly releases (24A, 24B, etc.), with new endpoints added each quarter without version bumps. [src1, src5]

| Property | Value |
|---|---|
| **Vendor** | Oracle |
| **System** | Oracle Fusion Cloud HCM (Release 24B) |
| **API Surface** | REST (primary), HDL (bulk inbound), HCM Extracts (bulk outbound), BIP (reports), SOAP (legacy) |
| **Current API Version** | 11.13.18.05 (resource version, stable across releases) |
| **Editions Covered** | Enterprise (single edition for cloud) |
| **Deployment** | Cloud (Oracle Cloud Infrastructure) |
| **API Docs URL** | [Oracle Fusion Cloud HCM REST API](https://docs.oracle.com/en/cloud/saas/human-resources/24b/farwh/) |
| **Status** | GA — quarterly feature releases (24A through 25A+) |

## API Surfaces & Capabilities

Oracle HCM Cloud offers five integration surfaces, each suited to different volume, direction, and latency requirements. REST handles real-time CRUD, HDL handles bulk inbound, HCM Extracts handle bulk outbound, BIP handles reporting, and SOAP remains for legacy integrations. [src1, src2, src4]

| API Surface | Protocol | Best For | Max Records/Request | Rate Limit | Real-time? | Bulk? |
|---|---|---|---|---|---|---|
| REST API | HTTPS/JSON | Individual worker CRUD, queries, real-time operations | 500 per page (limit param) | Fair-use ~60 req/s (429) | Yes | No |
| HDL (HCM Data Loader) | .dat files via REST upload or UCM | Bulk inbound: new hires, mass updates, benefits enrollment | 250 MB per file | 20 threads/pod | No | Yes |
| HCM Extracts | XML/CSV via UCM or FTP delivery | Bulk outbound: scheduled data feeds to downstream systems | Extract-dependent | ESS scheduler | No | Yes |
| BI Publisher (BIP) | HTTPS/XML or CSV | Reporting, ad-hoc outbound data extraction | Report-dependent | ESS scheduler | No | Yes |
| SOAP Web Services | HTTPS/XML | Legacy integrations, metadata operations | Varies by service | Shared with REST | Yes | No |
| HCM Atom Feeds | HTTPS/Atom XML | Change tracking, event-driven outbound notifications | N/A (feed-based) | Configurable | Yes | N/A |

## Rate Limits & Quotas

### Per-Request Limits

| Limit Type | Value | Applies To | Notes |
|---|---|---|---|
| Max records per REST page | 500 | REST API (all HCM resources) | Use offset + limit for pagination; default page size is 25 [src1] |
| Max HDL file size | 250 MB | .dat file upload | Split larger data sets into multiple files [src2] |
| Max concurrent HDL threads | 20 | Per pod | All HDL imports share the thread pool; large imports may block others [src2] |
| Max REST response payload | Not officially published | REST API | Practical limit ~50 MB for large query results |
| Max attachment size | 2 GB | REST API attachments | Per-file limit for document uploads |
| HCM Extract max rows | Not officially published | Per extract definition | Practical limit depends on extract complexity and pod resources [src4] |

[src1, src2]

### Rolling / Daily Limits

| Limit Type | Value | Window | Edition Differences |
|---|---|---|---|
| REST API calls | No published hard limit | Fair-use | Oracle uses dynamic throttling — ~60 req/s, returns 429 when exceeded [src5] |
| HDL import submissions | No published hard limit | Per pod | Queued; concurrent up to 20 threads across all running imports [src2] |
| HCM Extract runs | No published hard limit | Per pod | Subject to ESS scheduler capacity [src4] |
| BIP report runs | No published hard limit | Per pod | Subject to ESS scheduler capacity |

[src2, src5]

### Throttling Behavior

Oracle Fusion Cloud HCM does not publish fixed API rate limits. Instead, it applies fair-use throttling at the pod level, similar to Oracle Financials Cloud. When throttled, the API returns HTTP 429 with a Retry-After header. The practical threshold is approximately 60 requests per second, but this varies by pod load, time of day, and tenant configuration. There is no self-service way to check remaining quota — implement 429 handling with exponential backoff. [src5]

## Authentication

| Flow | Use When | Token Lifetime | Refresh? | Notes |
|---|---|---|---|---|
| OAuth 2.0 JWT Bearer | Server-to-server integrations (recommended) | 3600 seconds | No (re-authenticate) | Register Confidential Application in Oracle IDCS [src6] |
| OAuth 2.0 Client Credentials | Automated batch processes | 3600 seconds | No (re-authenticate) | Same IDCS registration as JWT [src6] |
| Basic Auth over SSL | Testing, simple integrations | Session-based | N/A | Username + password; not recommended for production |
| SAML 2.0 Bearer Token | SSO-federated user-context operations | Session timeout | N/A | SAML assertion in HTTP header over SSL |

[src6]

### Authentication Gotchas

- OAuth JWT Bearer flow via Oracle IDCS does not provide refresh tokens — your integration must re-authenticate every 3600 seconds by requesting a new access token. Hardcoding token expiry is risky because IDCS administrators can change the timeout. [src6]
- The integration user must have the correct HCM duty roles assigned (e.g., Human Resource Analyst, Integration Specialist) — API calls execute under the integration user's security context, and missing roles produce HTTP 403, not 401. Role assignment determines which workers are visible (data security). [src6]
- IDCS token endpoint URL varies by data center region: `https://{identity-domain}.identity.oraclecloud.com/oauth2/v1/token`. Using the wrong region endpoint returns connection errors, not auth errors. [src6]
- HDL imports submitted via REST inherit the security context of the integration user — the user must have the HCM Data Loader role AND the object-level security roles for the business objects being loaded. [src2]

## Constraints
<!-- Agents: read this section before recommending any integration approach from this unit.
     These are hard constraints that must not be violated. -->

- REST API is NOT suitable for bulk worker operations (>500 records). For mass hires, compensation updates, or benefits enrollment exceeding 500 records, use HDL. REST has no bulk endpoint equivalent to Salesforce Bulk API. [src1, src5]
- HDL .dat files must follow Oracle's exact Business Object structure with pipe-delimited fields and METADATA/MERGE/END blocks. Invalid formatting causes the entire file to fail validation before any records are processed. [src2]
- Payroll REST APIs (payrollRelationships, payrollResults, payslips, payrollBalances) require a separate Oracle Payroll license. Without the license, endpoints return 403 or empty result sets without a clear licensing error message. [src3]
- HCM Extracts are outbound-only — they cannot be used for inbound data loading. The only supported inbound bulk path is HDL. [src4]
- SOAP APIs for HCM are maintenance-only — Oracle does not add new SOAP services and recommends REST + HDL for all new integrations. SOAP may be removed in future releases. [src5]
- Worker records have complex employment hierarchy (Legal Employer > Assignment > Work Relationship) — REST API requires creating records in the correct hierarchical order or the entire transaction fails. [src1]
- Effective-dated records (assignments, compensation, etc.) require effective date parameters on REST calls. Omitting the effective date defaults to system date, which may create incorrect date-effective rows that are difficult to correct. [src1]

## Integration Pattern Decision Tree

```
START — User needs to integrate with Oracle HCM Cloud
├── What's the data direction?
│   ├── Inbound (writing to HCM)
│   │   ├── Volume < 500 records/operation?
│   │   │   ├── YES → REST API
│   │   │   │   ├── Hire new worker? → POST /workers
│   │   │   │   ├── Update assignment? → PATCH /workers/{id}/child/assignments/{id}
│   │   │   │   ├── Terminate worker? → POST /workers/{id}/child/workRelationships/{id}/action/terminate
│   │   │   │   └── Create absence? → POST /absences
│   │   │   └── NO → HDL (HCM Data Loader)
│   │   ├── Volume 500-50,000 records?
│   │   │   └── HDL — prepare .dat file, upload via hcmImportAndLoadData REST, poll status
│   │   └── Volume > 50,000 records?
│   │       └── HDL — split into multiple .dat files (<250 MB each), serialize submissions
│   ├── Outbound (reading from HCM)
│   │   ├── Real-time individual queries?
│   │   │   └── REST API: GET /workers, /assignments, /absences with query params
│   │   ├── Scheduled bulk extraction?
│   │   │   ├── Structured, repeatable feed? → HCM Extracts (define once, schedule via ESS)
│   │   │   └── Ad-hoc reporting? → BI Publisher report
│   │   └── Change tracking / CDC?
│   │       └── HCM Atom Feeds (track changes since last read)
│   └── Bidirectional
│       └── REST for real-time inbound + HCM Extracts for outbound + HDL for bulk inbound
├── What's the HCM module?
│   ├── Core HR (workers, assignments, employment)
│   │   └── REST or HDL — both fully supported
│   ├── Compensation (salary, bonus)
│   │   └── REST for individual updates; HDL for mass compensation changes
│   ├── Benefits (enrollment, life events)
│   │   └── HDL for open enrollment; REST for individual elections
│   ├── Payroll
│   │   └── REST (requires Payroll license); HDL for payroll elements
│   ├── Talent (goals, performance)
│   │   └── REST for CRUD; HDL for bulk goal assignments
│   └── Learning
│       └── REST for enrollments and completions
└── Error tolerance?
    ├── Zero-loss required → HDL with error file download + reconciliation
    └── Best-effort → REST with retry on 429/5xx
```

## Quick Reference

### Key REST Endpoints by Module

| Module | Resource | Endpoint Path | Operations | Notes |
|---|---|---|---|---|
| Core HR — Workers | workers | /hcmRestApi/resources/11.13.18.05/workers | GET, POST | Hire, query; child: assignments, workRelationships, names, emails, phones |
| Core HR — Assignments | assignments (child of workers) | /hcmRestApi/resources/11.13.18.05/workers/{id}/child/assignments | GET, PATCH | Update assignment; effective-dated |
| Core HR — Work Relationships | workRelationships (child) | /hcmRestApi/resources/11.13.18.05/workers/{id}/child/workRelationships | GET, POST | Create/terminate; action endpoints |
| Core HR — Persons | emps | /hcmRestApi/resources/11.13.18.05/emps | GET | Query employees with expanded attributes |
| Compensation — Salary | salaries | /hcmRestApi/resources/11.13.18.05/salaries | GET, POST, PATCH | Individual salary management |
| Absence — Absences | absences | /hcmRestApi/resources/11.13.18.05/absences | GET, POST, PATCH | Leave requests and balances |
| Payroll — Relationships | payrollRelationships | /hcmRestApi/resources/11.13.18.05/payrollRelationships | GET | Requires Payroll license [src3] |
| Payroll — Payslips | payslips | /hcmRestApi/resources/11.13.18.05/payslips | GET | Requires Payroll license |
| Talent — Goals | goals | /hcmRestApi/resources/11.13.18.05/goals | GET, POST, PATCH | Goal management |
| Talent — Performance | performanceDocuments | /hcmRestApi/resources/11.13.18.05/performanceDocuments | GET, PATCH | Performance reviews |
| Learning — Enrollments | learningRecordEnrollments | /hcmRestApi/resources/11.13.18.05/learningRecordEnrollments | GET, POST | Training enrollment |
| HDL Import | hcmImportAndLoadData | /hcmRestApi/resources/11.13.18.05/hcmImportAndLoadData | POST | HDL file upload + import trigger |
| HCM Atom Feeds | atomFeeds | /hcmRestApi/resources/11.13.18.05/atomFeeds/{feedId} | GET | Change tracking feeds |

[src1, src3]

## Step-by-Step Integration Guide

### 1. Authenticate via OAuth 2.0 JWT Bearer

Register a Confidential Application in Oracle IDCS, obtain Client ID and Client Secret, then request an access token. [src6]

```bash
# Input:  IDCS Client ID, Client Secret, Identity Domain URL
# Output: Access token (JWT, 3600s lifetime)

curl -X POST \
  "https://{identity-domain}.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "{client_id}:{client_secret}" \
  -d "grant_type=client_credentials&scope=urn:opc:resource:consumer::all"
```

**Verify**: Response contains `"access_token"` field and `"expires_in": 3600`

### 2. Query Workers via REST

Use the workers endpoint to retrieve employee data by person number or other criteria. [src1]

```bash
# Input:  Access token, query criteria
# Output: JSON array of worker records

curl -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers?q=PersonNumber=12345&expand=assignments,names,emails&onlyData=true" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/json"
```

**Verify**: Response contains `"items"` array with `PersonNumber`, `assignments`, `names` child objects

### 3. Hire a New Worker via REST

POST a new worker with the required work relationship and assignment details. Oracle HCM requires the correct hierarchy: Person > Work Relationship > Assignment. [src1]

```bash
# Input:  Access token, new hire details
# Output: PersonId and AssignmentId

curl -X POST \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/vnd.oracle.adf.resourceitem+json" \
  -d '{
    "DateOfBirth": "1990-05-15",
    "names": [{
      "LegislationCode": "US",
      "FirstName": "Jane",
      "LastName": "Smith"
    }],
    "emails": [{
      "EmailType": "W1",
      "EmailAddress": "jane.smith@company.com"
    }],
    "workRelationships": [{
      "LegalEmployerName": "US Legal Entity",
      "WorkerType": "E",
      "StartDate": "2026-04-01",
      "assignments": [{
        "BusinessUnitName": "US Business Unit",
        "JobName": "Software Engineer",
        "DepartmentName": "Engineering",
        "AssignmentCategory": "FR",
        "ActionCode": "HIRE"
      }]
    }]
  }'
```

**Verify**: Response HTTP 201 with `PersonId` and child `workRelationships[0].assignments[0].AssignmentId` populated

### 4. Upload HDL File for Bulk Import

For bulk operations, prepare a .dat file following Oracle's HDL Business Object format, then upload and trigger import via the hcmImportAndLoadData REST endpoint. [src2, src5]

```bash
# Step 4a: Prepare HDL .dat file (example: Worker business object)
# File: Worker.dat
# METADATA|Worker|PersonNumber|DateOfBirth|...
# MERGE|Worker|EMP-001|1990-05-15|...
# MERGE|Worker|EMP-002|1988-11-20|...
# END

# Step 4b: ZIP the .dat file and base64-encode
base64 Worker.zip > Worker_b64.txt

# Step 4c: Upload and trigger import via REST
curl -X POST \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/hcmImportAndLoadData" \
  -H "Authorization: Bearer {access_token}" \
  -H "Content-Type: application/vnd.oracle.adf.resourceitem+json" \
  -d '{
    "ContentType": "zip",
    "FileName": "Worker.zip",
    "DocumentContent": "{base64_encoded_zip}"
  }'
```

**Verify**: Response returns `FlowId`; poll `GET /hcmImportAndLoadData/{FlowId}` until status = `COMPLETED`

### 5. Configure and Run HCM Extract for Outbound Feed

Use HCM Extracts for scheduled outbound data delivery to downstream systems. [src4]

```
HCM Extract setup (via HCM Cloud UI):
1. Navigate: Data Exchange > HCM Extracts
2. Create new extract definition → select business objects (e.g., Worker, Assignment)
3. Configure output format (XML, CSV)
4. Set delivery: UCM, FTP, or BI Publisher
5. Schedule via ESS (daily, weekly, event-triggered)

Programmatic trigger via REST:
POST /hcmRestApi/resources/11.13.18.05/submitESSJobRequest
{
  "JobPackageName": "/oracle/apps/ess/hcm/dataExchange/",
  "JobDefName": "HcmExtractLauncher",
  "ESSParameters": "{ExtractName}"
}
```

**Verify**: Poll ESS job status until `SUCCEEDED`; download output file from UCM

### 6. Handle Pagination for Large Worker Queries

Oracle REST API returns paginated results with `hasMore`, `offset`, and `limit` parameters. Maximum page size is 500. [src1]

```python
# Input:  API base URL, access token
# Output: Complete list of all active workers

import requests  # requests==2.31.0

base_url = "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05"
headers = {"Authorization": f"Bearer {access_token}"}
all_workers = []
offset = 0
limit = 500  # max page size

while True:
    resp = requests.get(
        f"{base_url}/workers",
        headers=headers,
        params={
            "q": "ActiveFlag=Y",
            "offset": offset,
            "limit": limit,
            "onlyData": "true",
            "expand": "names,assignments"
        }
    )
    resp.raise_for_status()
    data = resp.json()
    all_workers.extend(data.get("items", []))
    if not data.get("hasMore", False):
        break
    offset += limit
```

**Verify**: `len(all_workers)` matches expected active headcount; last page has `"hasMore": false`

### 7. Implement Retry Logic for 429 Throttling

Oracle returns HTTP 429 when fair-use throttling kicks in. Implement exponential backoff. [src5]

```python
import time
import requests

def hcm_api_call(url, headers, method="GET", data=None, max_retries=5):
    for attempt in range(max_retries):
        if method == "GET":
            resp = requests.get(url, headers=headers)
        else:
            resp = requests.post(url, headers=headers, json=data)

        if resp.status_code == 429:
            retry_after = int(resp.headers.get("Retry-After", 2 ** attempt))
            time.sleep(retry_after)
            continue
        elif resp.status_code >= 500:
            time.sleep(2 ** attempt)
            continue
        else:
            resp.raise_for_status()
            return resp.json()

    raise Exception(f"Max retries ({max_retries}) exceeded for {url}")
```

**Verify**: Function returns data on 200; retries on 429/5xx; raises after max retries

## Code Examples

### Python: Hire New Worker with Error Handling

```python
# Input:  Oracle HCM host, OAuth token, new hire data dict
# Output: Created PersonId or error details

import requests  # requests==2.31.0

def hire_worker(host, token, hire_data):
    url = f"https://{host}/hcmRestApi/resources/11.13.18.05/workers"
    headers = {
        "Authorization": f"Bearer {token}",
        "Content-Type": "application/vnd.oracle.adf.resourceitem+json"
    }
    resp = requests.post(url, headers=headers, json=hire_data)

    if resp.status_code == 201:
        person_id = resp.json().get("PersonId")
        return {"success": True, "person_id": person_id}
    elif resp.status_code == 429:
        retry_after = resp.headers.get("Retry-After", "60")
        return {"success": False, "error": "throttled", "retry_after": retry_after}
    elif resp.status_code == 403:
        return {"success": False, "error": "forbidden",
                "detail": "Check integration user HCM duty roles and data security"}
    else:
        return {"success": False, "status": resp.status_code, "detail": resp.text}
```

### JavaScript/Node.js: Query Workers by Department

```javascript
// Input:  Oracle host URL, OAuth token, department name
// Output: Array of worker objects in that department

// node-fetch@3.3.2
import fetch from 'node-fetch';

async function getWorkersByDepartment(host, token, department) {
  const url = new URL(`https://${host}/hcmRestApi/resources/11.13.18.05/workers`);
  url.searchParams.set('q', `assignments.DepartmentName=${department}`);
  url.searchParams.set('expand', 'names,assignments,emails');
  url.searchParams.set('onlyData', 'true');
  url.searchParams.set('limit', '500');

  const resp = await fetch(url.toString(), {
    headers: {
      'Authorization': `Bearer ${token}`,
      'Content-Type': 'application/json'
    }
  });

  if (!resp.ok) {
    throw new Error(`Worker query failed: ${resp.status} ${resp.statusText}`);
  }
  const data = await resp.json();
  return data.items || [];
}
```

### cURL: Test Authentication and Worker Query

```bash
# Input:  IDCS domain, client_id, client_secret
# Output: JSON with access_token field, then worker records

# Step 1: Get token
curl -s -X POST \
  "https://{idcs-domain}.identity.oraclecloud.com/oauth2/v1/token" \
  -H "Content-Type: application/x-www-form-urlencoded" \
  -u "{client_id}:{client_secret}" \
  -d "grant_type=client_credentials&scope=urn:opc:resource:consumer::all" \
  | python -m json.tool

# Step 2: Test token against workers endpoint
curl -s -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers?limit=5&onlyData=true" \
  -H "Authorization: Bearer {access_token}" \
  | python -m json.tool
```

## Data Mapping

### HDL Worker Business Object — Key Field Mapping

| HDL Column | Business Object Field | Type | Required | Notes |
|---|---|---|---|---|
| PersonNumber | PERSON_NUMBER | String | Yes (for MERGE) | Unique person identifier; auto-generated if not provided on INSERT |
| DateOfBirth | DATE_OF_BIRTH | Date | No | Format: YYYY/MM/DD |
| LegislationCode | LEGISLATION_CODE | String | Yes | Country code (e.g., US, GB, DE) |
| FirstName (Name) | FIRST_NAME | String | Yes | Part of Name business object |
| LastName (Name) | LAST_NAME | String | Yes | Part of Name business object |
| LegalEmployerName (WorkRelationship) | LEGAL_EMPLOYER_NAME | String | Yes | Must match configured legal employer |
| WorkerType (WorkRelationship) | WORKER_TYPE | String | Yes | E=Employee, C=Contingent |
| StartDate (WorkRelationship) | START_DATE | Date | Yes | Work relationship start date |
| ActionCode (Assignment) | ACTION_CODE | String | Yes | HIRE, REHIRE, TRANSFER, etc. |
| BusinessUnitName (Assignment) | BUSINESS_UNIT_NAME | String | Yes | Must match configured BU |
| JobName (Assignment) | JOB_NAME | String | Yes | Must match configured job |
| DepartmentName (Assignment) | DEPARTMENT_NAME | String | Yes | Must match configured department |

### REST Worker Resource — Key Field Mapping

| REST Field | DB Column | Type | Required | Notes |
|---|---|---|---|---|
| PersonNumber | PERSON_NUMBER | String | Auto | Read-only on GET; auto-generated on POST |
| DateOfBirth | DATE_OF_BIRTH | Date | No | Format: YYYY-MM-DD in JSON |
| names[].FirstName | FIRST_NAME | String | Yes | Nested in names child array |
| names[].LastName | LAST_NAME | String | Yes | Nested in names child array |
| workRelationships[].LegalEmployerName | LEGAL_EMPLOYER_NAME | String | Yes | Nested hierarchy |
| workRelationships[].assignments[].AssignmentNumber | ASSIGNMENT_NUMBER | String | Auto | Auto-generated on hire |

### Data Type Gotchas

- HDL .dat files use YYYY/MM/DD date format with forward slashes, while REST API uses ISO 8601 (YYYY-MM-DD) — mixing formats causes silent failures in HDL or malformed dates in REST responses. [src1, src2]
- HDL uses pipe-delimited fields with METADATA/MERGE/END block structure — any deviation from this format (extra pipes, missing end markers) causes the entire file to fail pre-validation. [src2]
- Person names in HDL require separate Name business object rows linked by SourceSystemId — they are NOT inline columns on the Worker row. This is the #1 cause of HDL failures for new integrators. [src2]
- Effective-dated fields (salary, assignment changes) require EffectiveStartDate in REST calls — omitting it defaults to system date, creating incorrect date-effective history rows. [src1]

## Error Handling & Failure Points

### Common Error Codes

| Code | Meaning | Cause | Resolution |
|---|---|---|---|
| 400 | Bad Request | Invalid JSON payload, missing required fields, invalid effective date | Check field names (case-sensitive), required hierarchy (workRelationships > assignments) |
| 401 | Unauthorized | Invalid or expired access token | Re-authenticate via OAuth; check token expiry |
| 403 | Forbidden | Integration user lacks required HCM duty role or data security | Assign HCM roles; check Payroll license for payroll endpoints |
| 404 | Not Found | Invalid endpoint path or PersonId/AssignmentId does not exist | Verify resource version (11.13.18.05) and resource name |
| 409 | Conflict | Person number already exists, or concurrent update conflict | Check for duplicate PersonNumber; retry with jitter |
| 429 | Too Many Requests | Fair-use throttling threshold exceeded (~60 req/s) | Exponential backoff using Retry-After header value |
| 500 | Internal Server Error | Oracle server-side issue, often transient | Retry after 30-60 seconds; check Oracle Cloud status page |
| HDL-001 | HDL Validation Error | .dat file format invalid (missing METADATA, wrong delimiters) | Validate .dat file structure before upload |
| HDL-002 | HDL Reference Data Error | Referenced value (department, job, legal employer) not found | Pre-validate reference data via REST GET before preparing HDL files |

[src1, src2, src5]

### Failure Points in Production

- **HDL upload succeeds but import fails silently**: The hcmImportAndLoadData POST returns 200 for the file upload, but the import job may fail due to validation errors. Errors appear only in the HDL error log file, not in the REST response. Fix: `Always poll the import status AND download the error file via GET hcmImportAndLoadData/{FlowId}`. [src2]
- **Worker hire fails due to missing dependent setup**: Creating a worker requires valid Legal Employer, Business Unit, Job, Department, and Location — if any are missing or misconfigured, the hire fails with a generic 400 error. Fix: `Pre-validate all reference data via REST GET queries before attempting the hire`. [src1]
- **Effective date confusion creates incorrect history**: Omitting EffectiveStartDate on assignment updates defaults to the system date, creating a new date-effective row that may not be the intended change date. Fix: `Always explicitly set EffectiveStartDate on every effective-dated operation`. [src1]
- **OAuth token expires during HDL processing**: Large HDL imports can take hours to process. The import continues server-side, but your polling calls fail with 401. Fix: `Re-authenticate before each poll request; never cache tokens beyond 3500s`. [src6]
- **Payroll endpoints return 403 without clear error**: Without the Payroll license, payroll REST endpoints return 403 or empty results. The error body does not mention licensing. Fix: `Verify Payroll license is active before building integrations against payroll endpoints`. [src3]
- **HDL MERGE vs INSERT confusion**: MERGE mode updates existing records or creates new ones. INSERT fails if the record exists. Using INSERT for idempotent integrations causes failures on retry. Fix: `Always use MERGE mode for production integrations to support retry scenarios`. [src2]

## Anti-Patterns

### Wrong: Querying all workers one-at-a-time to find changes

```python
# BAD — O(N) API calls for N workers; hits throttling quickly
for person_id in all_person_ids:
    resp = requests.get(f"{base}/workers/{person_id}", headers=headers)
    if resp.json()["LastUpdateDate"] > last_sync:
        process_change(resp.json())
```

### Correct: Use HCM Atom Feeds for change detection

```python
# GOOD — single feed request returns all changes since last read
resp = requests.get(
    f"{base}/atomFeeds/workers?since={last_sync_token}",
    headers=headers
)
for entry in parse_atom(resp.text):
    process_change(entry)
```

### Wrong: Using REST for mass compensation update

```python
# BAD — 10,000 individual PATCH calls for annual salary review
for emp in employees:
    requests.patch(
        f"{base}/salaries/{emp['salary_id']}",
        json={"Amount": emp["new_salary"]},
        headers=headers
    )
```

### Correct: Use HDL for bulk compensation changes

```python
# GOOD — single HDL file upload for any volume
import csv, base64, zipfile, io

buf = io.StringIO()
buf.write("METADATA|Salary|AssignmentNumber|SalaryAmount|DateFrom|...\n")
for emp in employees:
    buf.write(f"MERGE|Salary|{emp['assignment']}|{emp['new_salary']}|2026-04-01|...\n")
buf.write("END\n")

# ZIP, base64-encode, upload via hcmImportAndLoadData
zip_buf = io.BytesIO()
with zipfile.ZipFile(zip_buf, 'w') as zf:
    zf.writestr("Salary.dat", buf.getvalue())
encoded = base64.b64encode(zip_buf.getvalue()).decode()

requests.post(f"{base}/hcmImportAndLoadData", json={
    "ContentType": "zip",
    "FileName": "Salary.zip",
    "DocumentContent": encoded
}, headers=headers)
```

### Wrong: Ignoring effective dates on assignment updates

```python
# BAD — omitting EffectiveStartDate creates unintended history
requests.patch(
    f"{base}/workers/{person_id}/child/assignments/{assignment_id}",
    json={"DepartmentName": "Finance"},
    headers=headers
)
```

### Correct: Always specify effective date

```python
# GOOD — explicit effective date for clean date-effective history
requests.patch(
    f"{base}/workers/{person_id}/child/assignments/{assignment_id}",
    json={
        "DepartmentName": "Finance",
        "EffectiveStartDate": "2026-04-01"
    },
    headers=headers
)
```

## Common Pitfalls

- **Assuming REST handles bulk like Salesforce Bulk API**: Oracle HCM REST has no bulk endpoint. Developers build REST-based integrations for 10K+ records, then hit 429 throttling in production. Fix: `Design for HDL from day one if volume exceeds 500 records per operation`. [src5]
- **Building payroll integrations without verifying license**: Payroll REST endpoints exist in the API documentation regardless of licensing. Developers build against them in sandboxes (which may have Payroll enabled), then fail in production. Fix: `Confirm Payroll license with the Oracle admin before any payroll integration design`. [src3]
- **Not downloading HDL error files**: When HDL fails, developers see "FAILED" status but don't download the error output file, missing the actual validation errors. Fix: `Always download the HDL result/error file after every import, regardless of status`. [src2]
- **Hardcoding the 3600s token lifetime**: IDCS administrators can change token expiry settings. Fix: `Read the expires_in field from the token response and refresh proactively at 90% of lifetime`. [src6]
- **Using INSERT mode in HDL for production**: INSERT mode fails if a record already exists, breaking retry scenarios. Fix: `Always use MERGE mode in production HDL integrations`. [src2]
- **Ignoring the hierarchical worker data model**: Creating workers requires nested objects (Person > WorkRelationship > Assignment). Flat integration designs miss required hierarchy and fail with cryptic 400 errors. Fix: `Study the Worker composite object structure before designing any integration`. [src1]

## Diagnostic Commands

```bash
# Test OAuth authentication
curl -s -X POST \
  "https://{idcs}.identity.oraclecloud.com/oauth2/v1/token" \
  -u "{client_id}:{client_secret}" \
  -d "grant_type=client_credentials&scope=urn:opc:resource:consumer::all" \
  | python -m json.tool

# Query first 5 workers (verifies API connectivity + HCM access)
curl -s -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers?limit=5&onlyData=true" \
  -H "Authorization: Bearer {token}" \
  | python -m json.tool

# Check HDL import status
curl -s -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/hcmImportAndLoadData/{FlowId}" \
  -H "Authorization: Bearer {token}" \
  | python -m json.tool

# Verify a specific worker exists
curl -s -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers?q=PersonNumber={person_number}&onlyData=true" \
  -H "Authorization: Bearer {token}" \
  | python -m json.tool

# List available HCM Atom Feeds
curl -s -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/atomFeeds" \
  -H "Authorization: Bearer {token}" \
  | python -m json.tool

# Describe workers resource (field metadata)
curl -s -X GET \
  "https://{host}.fa.{dc}.oraclecloud.com/hcmRestApi/resources/11.13.18.05/workers/describe" \
  -H "Authorization: Bearer {token}" \
  | python -m json.tool
```

## Version History & Compatibility

| Release | Release Date | Status | Key Changes | Migration Notes |
|---|---|---|---|---|
| 24B | 2024-07 | Current | Expanded workers REST resource; enhanced HDL error reporting | Evaluate new child objects on workers resource |
| 24A | 2024-01 | Supported | HCM Atom Feeds GA; new absence management REST endpoints | Atom Feeds replace polling for change detection |
| 23D | 2023-10 | Supported | New talent management REST endpoints (goals, performance) | New resources for talent integrations |
| 23C | 2023-07 | Supported | HDL performance improvements; enhanced compensation REST | No breaking changes |
| 23B | 2023-04 | Supported | hcmImportAndLoadData REST endpoint for HDL uploads | Replaces UCM-only upload workflow |
| 23A | 2023-01 | Supported | Baseline for current HCM REST documentation set | Minimum recommended version |

[src1, src2]

### Deprecation Policy

Oracle Fusion Cloud HCM follows a quarterly release cadence (A/B/C/D per year). REST API resource version 11.13.18.05 has been stable for multiple years — Oracle adds new endpoints and child resources without changing the version number. SOAP services are considered legacy and not recommended for new development. Oracle provides a minimum 12-month notice before any breaking change via the What's New documentation. [src1]

## When to Use / When Not to Use

| Use When | Don't Use When | Use Instead |
|---|---|---|
| Real-time individual worker operations (hire, terminate, query) <500 records | Bulk employee imports >500 records (annual new hire batch, migration) | HDL via hcmImportAndLoadData |
| Querying worker details, assignments, absence balances | Mass compensation changes (annual review for 10K+ employees) | HDL with Salary business object |
| Individual absence requests and approvals | Scheduled outbound HR data feeds to payroll/benefits vendors | HCM Extracts with scheduled delivery |
| Real-time worker verification for downstream systems | Large-scale data extraction for analytics | BI Publisher reports via ESS |
| Individual salary updates and one-off changes | Open enrollment for 10K+ employees | HDL with Benefits business objects |
| Change detection for real-time sync | Full data migration from another HCM system | HDL with full business object set |

## Important Caveats

- Oracle does not publish fixed API rate limits for HCM — fair-use throttling thresholds vary by pod, tenant size, and time of day. What works in development may hit 429s in production during payroll runs or open enrollment.
- Payroll REST APIs require a separate Oracle Payroll license. The documentation lists these endpoints regardless of licensing, leading developers to build against them without realizing the dependency.
- HDL is the only supported path for bulk inbound operations. Oracle HCM REST API has no bulk endpoint — any integration design for >500 records must use HDL.
- The hierarchical worker data model (Person > WorkRelationship > Assignment) is non-negotiable — flat data integration patterns that ignore this hierarchy will fail.
- Effective-dated operations are pervasive in HCM — nearly every update (assignment change, compensation, benefits) requires explicit effective dates. Omitting them creates incorrect date-effective history that is difficult to correct.
- HCM Extracts are outbound-only — they cannot load data. The naming suggests bidirectional capability, but extraction is strictly read-only.
- API endpoint availability depends on which Oracle HCM modules are licensed and opted in — not all endpoints listed in the documentation may be available in every tenant.

## Related Units
<!-- Generated from related_kos frontmatter -->

- [Oracle Financials Cloud API Capabilities](/business/erp-integration/oracle-financials-cloud-api/2026)
