Summary and recommendation
UKG Pro's REST API uses OAuth 2.0 client credentials combined with a tenant-specific API key header every request must include both Authorization: Bearer <token> and US-API-Key: <api_key> or it returns a 401.
Tokens expire in one hour;
implement refresh logic rather than caching tokens across sessions.
The base URL https://service.ultipro.com applies to US tenants only;
Canadian tenants use https://service.ultipro.ca, and EU tenants may have a separate subdomain.
API versioning is path-based (v1, v2);
always verify the current supported version on developer.ukg.com, as older versions are subject to deprecation without guaranteed notice.
The list-employees endpoint (GET /personnel/v1/employee-ids) returns internal UUIDs only - a second per-employee call to GET /personnel/v1/employees/{employeeId} is required to retrieve full profile data, which has meaningful throughput implications at scale.
Pagination uses offset-based query params (?page=1&per-page=100) with a maximum page size of 200.
Rate limits are not publicly documented with numeric thresholds;
implement exponential backoff on 429 responses and avoid concurrent high-volume calls.
Sensitive PII fields (SSN, DOB, bank info) are masked by default and require explicit data access permissions on the service account's security role.
For delta sync, GET /personnel/v1/employee-changes accepts a date range window but may not capture all field-level changes
validate coverage for the specific fields your integration depends on before relying on it as a source of truth.
UKG Pro has no native outbound webhook system;
event-driven integrations must poll the employee-changes endpoint on a schedule or route through UKG Integration Studio or Boomi-based connectors.
SCIM 2.0 is available at Enterprise tier but is provisioned per-tenant through the IdP connector (Okta or Entra ID), not via a static self-service URL
initial setup typically requires UKG support or an implementation partner.
API quick reference
| Has user API | Yes |
| Auth method | OAuth 2.0 (client credentials) + API key header |
| Base URL | Official docs |
| SCIM available | Yes |
| SCIM plan required | Enterprise (custom pricing; SCIM provisioning is available via IdP connectors for Okta and Microsoft Entra ID) |
Authentication
Auth method: OAuth 2.0 (client credentials) + API key header
Setup steps
- Log in to UKG Pro as a Super Admin and navigate to Menu > System Configuration > Security > Service Account Administration.
- Create a Service Account and note the Client ID and Client Secret.
- Obtain a customer-specific API key (US-API-Key or equivalent) from the UKG Pro tenant settings.
- POST to https://service.ultipro.com/authentication/v1/token with grant_type=client_credentials, client_id, and client_secret to receive a Bearer token.
- Include both the Authorization: Bearer
header and the US-API-Key: header on all subsequent requests.
Required scopes
| Scope | Description | Required for |
|---|---|---|
| people:read | Read employee/person records | GET employee and person endpoints |
| people:write | Create and update employee/person records | POST/PATCH employee endpoints |
| employment:read | Read employment status and job information | GET employment detail endpoints |
| employment:write | Update employment status and job information | POST/PATCH employment endpoints |
User object / data model
| Field | Type | Description | On create | On update | Notes |
|---|---|---|---|---|---|
| employeeId | string | UKG-assigned unique employee identifier | system-generated | immutable | Used as primary key in most endpoints |
| firstName | string | Employee legal first name | required | optional | |
| lastName | string | Employee legal last name | required | optional | |
| emailAddress | string | Primary work email address | required | optional | Used as login identifier when SSO is not configured |
| employeeNumber | string | Customer-defined employee number | optional | optional | Distinct from system employeeId |
| hireDate | date (ISO 8601) | Original hire date | required | optional | |
| jobTitle | string | Employee job title | optional | optional | |
| departmentCode | string | Department code from org structure | optional | optional | Must match a valid department in the tenant |
| locationId | string | Work location identifier | optional | optional | |
| employmentStatus | string (enum) | Active, Terminated, Leave, etc. | required | optional | Termination requires separate termination endpoint |
| supervisorId | string | employeeId of direct manager | optional | optional | |
| companyCode | string | Legal entity / company code within the tenant | required | optional | Multi-company tenants must specify correct code |
| payGroupCode | string | Payroll group assignment | optional | optional | |
| flsaStatus | string (enum) | Exempt or Non-Exempt classification | optional | optional | |
| ethnicity | string | EEO ethnicity classification | optional | optional | Sensitive field; access controlled by role |
| gender | string | Gender identity | optional | optional | Sensitive field; access controlled by role |
| dateOfBirth | date (ISO 8601) | Employee date of birth | optional | optional | PII; restricted scope required |
| terminationDate | date (ISO 8601) | Date of employment termination | n/a | set via termination endpoint |
Core endpoints
List all employees
- Method: GET
- URL:
https://service.ultipro.com/personnel/v1/employee-ids - Watch out for: Returns only employeeIds; a second call per employee is needed to fetch full profile details.
Request example
GET /personnel/v1/employee-ids?page=1&per-page=100
Authorization: Bearer <token>
US-API-Key: <api_key>
Response example
{
"data": [
{"employeeId": "EMP-001"},
{"employeeId": "EMP-002"}
],
"total": 500
}
Get employee details
- Method: GET
- URL:
https://service.ultipro.com/personnel/v1/employees/{employeeId} - Watch out for: Some sensitive fields (SSN, DOB) require elevated service account permissions and are masked by default.
Request example
GET /personnel/v1/employees/EMP-001
Authorization: Bearer <token>
US-API-Key: <api_key>
Response example
{
"employeeId": "EMP-001",
"firstName": "Jane",
"lastName": "Doe",
"emailAddress": "jane.doe@example.com",
"hireDate": "2022-03-15",
"employmentStatus": "Active"
}
Create new employee
- Method: POST
- URL:
https://service.ultipro.com/personnel/v1/employees - Watch out for: companyCode must exactly match a valid entity in the tenant or the request returns a 400 error.
Request example
POST /personnel/v1/employees
Content-Type: application/json
{
"firstName": "John",
"lastName": "Smith",
"emailAddress": "john.smith@example.com",
"hireDate": "2024-01-10",
"companyCode": "CORP01"
}
Response example
{
"employeeId": "EMP-999",
"status": "created"
}
Update employee
- Method: PATCH
- URL:
https://service.ultipro.com/personnel/v1/employees/{employeeId} - Watch out for: Not all fields are patchable via this endpoint; job/pay changes may require separate employment-change endpoints.
Request example
PATCH /personnel/v1/employees/EMP-001
Content-Type: application/json
{
"jobTitle": "Senior Engineer",
"departmentCode": "ENG-02"
}
Response example
{
"employeeId": "EMP-001",
"status": "updated"
}
Terminate employee
- Method: POST
- URL:
https://service.ultipro.com/personnel/v1/employees/{employeeId}/terminations - Watch out for: terminationReasonCode must match a code configured in the tenant's reason code table.
Request example
POST /personnel/v1/employees/EMP-001/terminations
Content-Type: application/json
{
"terminationDate": "2024-06-30",
"terminationReasonCode": "RESIGN"
}
Response example
{
"employeeId": "EMP-001",
"terminationDate": "2024-06-30",
"status": "terminated"
}
Get employment details
- Method: GET
- URL:
https://service.ultipro.com/personnel/v1/employees/{employeeId}/employment-details - Watch out for: Returns current snapshot only; historical employment records require the reporting/BI API or UKG Pro Workforce Intelligence.
Request example
GET /personnel/v1/employees/EMP-001/employment-details
Authorization: Bearer <token>
US-API-Key: <api_key>
Response example
{
"employeeId": "EMP-001",
"jobTitle": "Engineer",
"flsaStatus": "Exempt",
"payGroupCode": "BIWEEKLY"
}
Get changed employees (delta)
- Method: GET
- URL:
https://service.ultipro.com/personnel/v1/employee-changes - Watch out for: Date range window is limited; very large tenants may need to paginate and narrow date windows to avoid timeouts.
Request example
GET /personnel/v1/employee-changes?startDate=2024-01-01&endDate=2024-01-31
Authorization: Bearer <token>
US-API-Key: <api_key>
Response example
{
"data": [
{"employeeId": "EMP-001", "changeType": "UPDATE", "changedDate": "2024-01-15"}
]
}
OAuth 2.0 token request
- Method: POST
- URL:
https://service.ultipro.com/authentication/v1/token - Watch out for: Tokens expire in 1 hour. Implement token refresh logic; do not cache tokens across sessions without checking expiry.
Request example
POST /authentication/v1/token
Content-Type: application/x-www-form-urlencoded
grant_type=client_credentials
&client_id=<client_id>
&client_secret=<client_secret>
Response example
{
"access_token": "eyJ...",
"token_type": "Bearer",
"expires_in": 3600
}
Rate limits, pagination, and events
Rate limits: UKG Pro API rate limits are not publicly documented with specific numeric thresholds. Limits are enforced per tenant and per service account.
Rate-limit headers: Unknown
Retry-After header: Unknown
Rate-limit notes: Official docs do not publish specific request-per-minute or daily limits. Contact UKG support for tenant-specific throttling details. Bulk operations should use pagination and avoid concurrent high-volume calls.
Pagination method: offset
Default page size: 100
Max page size: 200
Pagination pointer: page and per-page (via query params ?page=1&per-page=100)
Webhooks available: No
Webhook notes: UKG Pro does not offer a native outbound webhook system for real-time event push as of the current documentation. Event-driven integrations rely on polling the employee-changes endpoint or using UKG's Integration Studio (middleware).
Alternative event strategy: Poll GET /personnel/v1/employee-changes on a scheduled basis, or use UKG Integration Studio / Boomi-based connectors for event-driven workflows.
SCIM API status
SCIM available: Yes
SCIM version: 2.0
Plan required: Enterprise (custom pricing; SCIM provisioning is available via IdP connectors for Okta and Microsoft Entra ID)
Endpoint: Tenant-specific; generated by the IdP connector (e.g., Okta UKG Pro SCIM app or Entra ID enterprise app). No single published static base URL.
Supported operations: Create User, Update User, Deactivate User, List Users
Limitations:
- SCIM endpoint URL is provisioned per-tenant via the IdP connector; not a self-service static URL.
- Group/role provisioning support varies by IdP connector version.
- Native SCIM server is not independently documented on developer.ukg.com; configuration is IdP-side.
- Google Workspace and OneLogin SCIM connectors are not officially listed as supported.
- Full attribute mapping may require UKG Professional Services engagement.
Common scenarios
Onboarding via API requires a POST to /personnel/v1/employees with firstName, lastName, emailAddress, hireDate, and companyCode as minimum required fields.
The companyCode must exactly match a valid entity configured in the tenant or the request returns a 400;
validate against reference data endpoints before submitting.
Capture the returned employeeId and use a subsequent PATCH to add jobTitle, departmentCode, supervisorId, and locationId
not all fields are writable in the initial POST, and job or pay changes may require separate employment-change endpoints rather than the core PATCH.
Termination is handled via POST to /personnel/v1/employees/{employeeId}/terminations with a terminationDate and terminationReasonCode;
the reason code must match a value in the tenant's configured reason code table.
If SCIM provisioning is active through Okta or Entra ID, the IdP detects the employmentStatus change on its next polling cycle
deprovisioning in connected apps is not real-time and may lag by up to the IdP's full sync interval (typically around 40 minutes for Okta).
For multi-company tenants, cross-company writes are not permitted;
the correct companyCode must be passed on every create and update operation.
Onboard a new hire from an HRIS integration
- POST to /authentication/v1/token to obtain a Bearer token using client credentials.
- POST to /personnel/v1/employees with required fields: firstName, lastName, emailAddress, hireDate, companyCode.
- Capture the returned employeeId from the response.
- PATCH /personnel/v1/employees/{employeeId} to add jobTitle, departmentCode, supervisorId, and locationId.
- Verify creation by GET /personnel/v1/employees/{employeeId}.
Watch out for: companyCode and departmentCode must exactly match values configured in the tenant; validate these against reference data endpoints before submitting.
Sync employee changes to a downstream system (delta sync)
- On a scheduled interval (e.g., every 15 minutes), GET /personnel/v1/employee-changes?startDate=
&endDate= . - For each employeeId in the response, GET /personnel/v1/employees/{employeeId} to fetch the full updated record.
- Map UKG fields to the downstream system's schema and upsert records.
- Store the current timestamp as last_run for the next polling cycle.
Watch out for: The employee-changes endpoint may not capture all field-level changes; test thoroughly for the specific fields your integration depends on.
Terminate an employee and deprovision access via SCIM
- POST to /personnel/v1/employees/{employeeId}/terminations with terminationDate and terminationReasonCode.
- If SCIM provisioning is active via Okta or Entra ID, the IdP will detect the employmentStatus change on its next sync cycle and deactivate the user in connected apps.
- Confirm deprovisioning by checking the user's status in the IdP and downstream applications.
Watch out for: SCIM deprovisioning is triggered by the IdP polling UKG, not by a real-time push; there may be a delay of up to the IdP's sync interval (typically 40 minutes for Okta) between termination in UKG and access revocation.
Why building this yourself is a trap
The two-header authentication requirement (Bearer token plus API key) is the most common source of silent integration failures - omitting either header returns a 401 with no indication of which credential is missing. The internal UUID returned by the list endpoint is not the human-readable employee number visible in the UI;
integrations that conflate the two will produce mismatched records in downstream systems. Because UKG Pro has no native webhook support, any integration built on the assumption of real-time event push will require a polling architecture instead, with all the latency and missed-change risk that entails.
Building an identity graph on top of UKG Pro requires careful handling of the supervisorId field (which references the manager's internal employeeId), companyCode for multi-entity tenants, and departmentCode from the org structure - all of which must be kept in sync as org changes occur.
The employee-changes endpoint is the practical mechanism for keeping that graph current, but its field-level change coverage is incomplete and must be validated per integration.
SCIM provisioning offloads some of this complexity to the IdP layer, but the lack of a static SCIM base URL and the requirement for professional services involvement on initial setup means SCIM is not a drop-in solution without upfront configuration investment.
Automate UKG workflows without one-off scripts
Stitchflow builds and maintains end-to-end IT automation across your SaaS stack, including apps without APIs. Built for exactly how your company works, with human approvals where they matter.