HR Tool - API Specification Document v3.1.7
Table of Contents
- 1. OVERVIEW
- 2. AUTHENTICATION (OAuth 2.0)
- 3. EMPLOYEE MANAGEMENT APIs
- 4. LEAVE TYPE MANAGEMENT APIs
- 5. LEAVE REQUEST MANAGEMENT APIs
- 6. POSITION MANAGEMENT APIs
- 7. JOB LISTINGS APIs
- 8. HOLIDAY ENTITLEMENTS APIs
- 9. DEPARTMENT MANAGEMENT APIs
- 10. ROLE MANAGEMENT APIs
- 11. POLICY MANAGEMENT APIs
- 12. DOCUMENT MANAGEMENT APIs
- 13. EMPLOYEE CONTRACT APIs
- 14. CONTRACT TEMPLATE APIs
- 15. COMPANY SETTINGS APIs
- 16. FILE UPLOAD API
- 17. MENU MANAGEMENT APIs
- 17. COMPANY PROVISION API
- 18. REPORT API
- 18. ERROR HANDLING
- 19. RATE LIMITING & SECURITY
- 20. INTEGRATION CHECKLIST FOR YOUR COMPANY
- APPENDIX A: QUICK REFERENCE
1. OVERVIEW
This document outlines the REST API specifications for the HR Tool system. The Phase 2 implementation introduces OAuth 2.0 authentication, providing enterprise-grade security and enabling Single Sign-On (SSO) capabilities.
1.1 Purpose
This API enables companies to integrate with the HR Tool for employee data synchronization, leave management, and user authentication. This also includes OAuth 2.0 implementation which allows HR Tool users to authenticate directly into their local platform using their HR Tool credentials.
1.2 Base URLs
| Environment | Base URL |
|---|---|
| Testing | http://xz-ai.info:8197 |
| Production | https://hr.shiftcare.com/api |
1.3 What's New in Phase 2
OAuth 2.0 Client Credentials Grant - Secure machine-to-machine authentication
JWT Access Tokens - RS256 signed tokens with 15-minute expiry
Enhanced Security - OWASP Top 10 compliance, rate limiting, audit logging
Improved Performance - Caching layer for faster API responses
2. AUTHENTICATION (OAuth 2.0)
IMPORTANT: All API endpoints require OAuth 2.0 authentication using Bearer tokens. Legacy authentication methods to be deprecated.
2.1 OAuth 2.0 Flow Overview
HR Tool implements the OAuth 2.0 Client Credentials Grant flow, suitable for server-to-server authentication where Shiftcare acts as the client.
Authentication Flow: Where Company is your entity.
1. Company → POST /oauth2/token with client credentials
2. HR Tool validates credentials and issues tokens
3. Company receives access_token (15 min)
4. Company uses access_token in Authorization header for API calls
2.2 Obtaining Access Tokens
Endpoint: POST /oauth2/token
Description: Obtain access token using client credentials
Request Headers:
| Header | Value |
|---|---|
| Content-Type | application/x-www-form-urlencoded |
Request Body (form-urlencoded):
| Parameter | Required | Description |
|---|---|---|
| grant_type | Yes | Must be client_credentials |
| client_id | Yes | Your application's client ID (provided by HR Tool) |
| client_secret | Yes | Your application's client secret (provided by HR Tool) |
| scope | Optional | Space-delimited scopes (default: read write) |
Example Request (cURL):
curl -X POST https://hr.shiftcare.com/api/oauth2/token \
-H "Content-Type: application/x-www-form-urlencoded" \
-d "grant_type=client_credentials" \
-d "client_id=YOUR_CLIENT_ID" \
-d "client_secret=YOUR_CLIENT_SECRET"
Success Response (200 OK):
{
"access_token": "eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...",
"token_type": "Bearer",
"expires_in": 900,
"scope": "read write"
}
Response Fields:
| access_token | JWT access token (valid for 15 minutes) |
|---|---|
| token_type | Always "Bearer" - use in Authorization header |
| expires_in | Token lifetime in seconds (900 = 15 minutes) |
| scope | Granted permissions (space-delimited) |
2.3 Using Access Tokens
Include the access token in the Authorization header of all API requests:
Authorization: Bearer YOUR_ACCESS_TOKEN
Example API Request:
curl -X GET https://hr.shiftcare.com/api/hr/v1/employees \
-H "Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9..."
2.4 JWT Token Structure
Access tokens are JSON Web Tokens (JWT) signed with RS256 algorithm. The token contains:
Standard Claims:
iss - Issuer (HR Tool)
sub - Subject (client_id)
aud - Audience (HR Tool API)
exp - Expiration time (Unix timestamp)
iat - Issued at (Unix timestamp)
jti - JWT ID (unique token identifier)
Token Verification:
Public keys for JWT verification are available at:
GET https://hr.shiftcare.com/api/oauth2/jwks
2.5 Mandatory Header for Client Credentials Grant
All business APIs accessed with a token obtained via client_credentials grant MUST include this header:
X-Enterprise-Id: {your-enterprise-id}
Location: Request Header
Required: YES
Description: Enterprise unique ID in the HR system (multi-tenant isolation)
Error: Missing or invalid value will return 400/403 Forbidden
Note: COMPANY PROVISION API No need to transfer X-Enterprise Id
3. EMPLOYEE MANAGEMENT APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token in Authorization header
3.1 Get Employee List
Endpoint: GET /hr/v1/employees
Description: Retrieve paginated list of employees with filtering options
scope: employee:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
| status | integer | 0=All, 1=Active, 2=Resigned, 3=Offboarding |
Example Request:
GET /hr/v1/employees?page=1&size=20&status=1
Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"employeeId": 1997903282458996738,
"firstName": "John",
"lastName": "Smith",
"email": "john.smith@example.com",
"phoneCode": "AU",
"phone": "+61 412345678",
"status": "1",
"employmentType": "1",
"createdDate": "2024-12-08T13:37:16",
"updatedDate": "2024-12-15T09:20:30"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
3.2 Create Employee
Endpoint: POST /hr/v1/employees
Description: Create a new employee record. Your company can call this endpoint to sync employee data from your platform to the HR Tool.
scope: employee:write
Request Body (JSON):
{
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phoneCode": "AU",
"phone": "+61 423456789",
"position": "Support Worker",
"employmentType": "1",
"hiredOn": "2024-01-15",
"username": "janedoe",
"roleId": "134",
"workPhoneCode": "AU",
"workPhone": "+24 325432345",
"employmentType": "1",
"country": "United States",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "Postal code",
"gender": "male",
"dateOfBirth": "1999-9-9",
"externalId": "12423123"
}
Required Fields:
firstName, lastName, email, phone, phoneCode, username, role
Note:
Employment type (1=Full-time, 2=Part-time, 3=Internship, 4=Contractor, 5=Casual, 6=Others)
roleId: using roleid from the role API
externalId: External system identifier
gender: must be male, female, non-binary, or prefer-not-to-say
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"employeeId": 2046765589981163521,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phoneCode": "AU",
"phone": "+61 387654321",
"position": "Support Worker",
"status": "1",
"hiredOn": "2026-03-26",
"externalId": "shiftcare-312322",
"workPhoneCode": "AU",
"workPhone": "+24 325432345",
"employmentType": "1",
"country": "United States",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "Postal code",
"gender": "male",
"dateOfBirth": "1999-9-9",
"createdDate": "2026-04-22T01:38:37",
"updatedDate": "2026-04-22T01:38:37"
}
}
3.3 Get Employee Details
Endpoint: GET /hr/v1/employees/{employeeId}
Description: Retrieve detailed information for a specific employee.
scope: employee:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"employeeId": 2046765589981163521,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phoneCode": "AU",
"phone": "+61 387654321",
"position": "Support Worker",
"status": "1",
"hiredOn": "2026-03-26",
"externalId": "shiftcare-312322",
"workPhoneCode": "AU",
"workPhone": "+24 325432345",
"employmentType": "1",
"country": "United States",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "Postal code",
"createdDate": "2026-04-22T01:38:37",
"updatedDate": "2026-04-22T01:38:37"
}
}
3.4 Update Employee
Endpoint: PUT /hr/v1/employees/{employeeId}
Description: Update existing employee information
scope: employee:write
Path Parameters:
employeeId - Employee ID from HR Tool
Request Body: Same as Create Employee, only include fields to update
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"employeeId": 2046765589981163521,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phoneCode": "AU",
"phone": "+61 387654321",
"position": "Support Worker",
"status": "1",
"hiredOn": "2026-03-26",
"externalId": "shiftcare-312322",
"workPhoneCode": "AU",
"workPhone": "+24 325432345",
"employmentType": "1",
"country": "United States",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "Postal code",
"gender": "male",
"dateOfBirth": "1999-9-9",
"createdDate": "2026-04-22T01:38:37",
"updatedDate": "2026-04-22T01:38:37"
}
}
3.5 Delete Employee
Endpoint: DELETE /hr/v1/employees/{employeeId}
Description: Soft delete an employee (marks as inactive)
scope: employee:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
3.6 Offboard Employee
Endpoint: PUT /hr/v1/employees/{employeeId}/offboard
Description: Mark employee as resigned. Employee record is retained but status changed to RESIGNED.
scope: employee:admin
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| resignationDate | String | Resignation date (yyyy-MM-dd) |
| reason | String | Resignation reason (maxlength: 500) |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"employeeId": 2046765589981163521,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phoneCode": "AU",
"phone": "+61 387654321",
"position": "Support Worker",
"status": "2",
"hiredOn": "2026-03-26",
"externalId": "shiftcare-312322",
"workPhoneCode": "AU",
"workPhone": "+24 325432345",
"employmentType": "1",
"country": "United States",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "Postal code",
"createdDate": "2026-04-22T01:38:37",
"updatedDate": "2026-04-22T01:38:37"
}
}
3.7 Restore Employee
Endpoint: PUT /hr/v1/employees/{employeeId}/restore
Description: Reactivate a previously resigned employee. Changes status back to ACTIVE.
scope: employee:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"employeeId": 2046765589981163521,
"firstName": "Jane",
"lastName": "Doe",
"email": "jane.doe@example.com",
"phoneCode": "AU",
"phone": "+61 387654321",
"position": "Support Worker",
"status": "1",
"hiredOn": "2026-03-26",
"externalId": "shiftcare-312322",
"workPhoneCode": "AU",
"workPhone": "+24 325432345",
"employmentType": "1",
"country": "United States",
"address1": "123 Main Street",
"address2": "Apt 4B",
"city": "New York",
"province": "NY",
"postalCode": "Postal code",
"createdDate": "2026-04-22T01:38:37",
"updatedDate": "2026-04-22T01:38:37"
}
}
4. LEAVE TYPE MANAGEMENT APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token in Authorization header
4.1 Get Leave Type List
Endpoint: GET /hr/v1/leave-types
Description: Retrieve paginated list of leave types
scope: leaveType:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
Example Request:
GET /hr/v1/leave-types?page=1&size=20 Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"leaveTypeId": 1001,
"leaveName": "Annual Leave",
"leaveType": "1",
"entitlement": 152.00,
"accrualFrequency": "4",
"resetDate": "1",
"carryOverPolicy": 40,
"carryOverStatus": "1",
"paidLeaveStatus": "1",
"maxDaysAllowed": 10,
"createDate": "2026-04-01T10:30:00",
"updatedDate": "2026-04-01T10:30:00"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
4.2 Create Leave Type
Endpoint: POST /hr/v1/leave-types
Description: Create a new leave type in the system
scope: leaveType:write
Request Body (JSON):
{
"leaveName": "Annual Leave",
"leaveType": "1",
"entitlement": 152.00,
"accrualFrequency": "4",
"resetDate": "1",
"carryOverPolicy": 40,
"carryOverStatus": "1",
"paidLeaveStatus": "1",
"maxDaysAllowed": 10
}
Required Fields:
leaveName - Leave type name
leaveType - Leave type code (see enum values below)
All Fields:
| Field | Type | Required | Description |
|---|---|---|---|
| leaveName | String | Yes | Leave type name |
| leaveType | String | Yes | Leave type code: 1=Annual Leave, 2=Sick Leave, 3=Maternity Leave, 4=Long Service Leave, 5=Paid Leave, 6=Personal Leave, 7=Other Unpaid Leave, 8=Time off in lieu, 9=Maternity/Paternity Leave, 10=Bereavement Leave, 11=Birthday leave, 12=Carer's leave, 13=Floating Public Holiday |
| entitlement | Decimal | No | Entitlement (Hours/Year) |
| accrualFrequency | String | No | 0=Weekly, 1=Monthly, 2=Quarterly, 3=Semi-Monthly, 4=Yearly |
| resetDate | String | No | 1=Anniversary Date, 2=Calendar Year |
| carryOverPolicy | Long | No | Maximum hours allowed to carry over |
| carryOverStatus | String | No | 1=Allow, 2=Reject |
| paidLeaveStatus | String | No | 0=Unpaid, 1=Paid |
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"leaveTypeId": 1001,
"leaveName": "Annual Leave",
"leaveType": "1",
"entitlement": 152.00,
"accrualFrequency": "4",
"resetDate": "1",
"carryOverPolicy": 40,
"carryOverStatus": "1",
"paidLeaveStatus": "1",
"maxDaysAllowed": 10,
"createDate": "2026-04-22T10:30:00",
"updatedDate": "2026-04-22T10:30:00"
}
}
4.3 Get Leave Type Details
Endpoint: GET /hr/v1/leave-types/{leaveTypeId}
Description: Retrieve detailed information for a specific leave type.
scope: leaveType:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"leaveTypeId": 1001,
"leaveName": "Annual Leave",
"leaveType": "1",
"entitlement": 152.00,
"accrualFrequency": "4",
"resetDate": "1",
"carryOverPolicy": 40,
"carryOverStatus": "1",
"paidLeaveStatus": "1",
"maxDaysAllowed": 10,
"createDate": "2026-04-01T10:30:00",
"updatedDate": "2026-04-01T10:30:00"
}
}
4.4 Update Leave Type
Endpoint: PUT /hr/v1/leave-types/{leaveTypeId}
Description: Update leave type information
scope: leaveType:write
Path Parameters:
leaveTypeId (required) - Leave type unique identifier
Request Body: Same fields as Create Leave Type, only include fields to update
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"leaveTypeId": 1001,
"leaveName": "Annual Leave (Updated)",
"leaveType": "1",
"entitlement": 160.00,
"accrualFrequency": "4",
"resetDate": "1",
"carryOverPolicy": 40,
"carryOverStatus": "1",
"paidLeaveStatus": "1",
"maxDaysAllowed": 10,
"createDate": "2026-04-01T10:30:00",
"updatedDate": "2026-04-22T14:00:00"
}
}
4.5 Delete Leave Type
Endpoint: DELETE /hr/v1/leave-types/{leaveTypeId}
Description: Delete a leave type record
scope: leaveType:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
5. LEAVE REQUEST MANAGEMENT APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token in Authorization header
5.1 Get Leave Request List
Endpoint: GET /hr/v1/leave-requests
Description: Retrieve paginated list of leave requests
scope: leaveRequest:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
| status | String | Leave request status: 1=Approved, 3=Pending, 4=Rejected |
Example Request:
GET /hr/v1/leave-requests?page=1&size=20 Authorization: Bearer eyJhbGciOiJSUzI1NiIsInR5cCI6IkpXVCJ9...
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"rejectReason": null,
"approverId": null,
"approverName": null,
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T10:00:00"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
5.2 Create Leave Request
Endpoint: POST /hr/v1/leave-requests
Description: Create a new leave requests in the system
scope: leaveRequest:write
Request Body (JSON):
{
"employeeId": 2046765589981163521,
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"externalId": "4234"
}
Required Fields:
employeeId - Employee ID from HR Tool
leaveType - Leave type code (1-13, see Leave Type enum values in section 4.3)
fromDateTime - Start date and time (format: yyyy-MM-dd HH:mm)
toDateTime - End date and time (format: yyyy-MM-dd HH:mm)
All Fields:
| Field | Type | Required | Description |
|---|---|---|---|
| employeeId | Long | Yes | Employee ID |
| leaveType | String | Yes | Leave type code (1-13, see section 4.3) |
| fromDateTime | String | Yes | From date and time (yyyy-MM-dd HH:mm) |
| toDateTime | String | Yes | To date and time (yyyy-MM-dd HH:mm) |
| notes | String | No | Leave request notes |
| totalDays | Decimal | No | Total leave days |
| externalId | String | No | External system identifier |
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T10:00:00"
}
}
5.3 Get Leave Request Details
Endpoint: GET /hr/v1/leave-requests/{leaveId}
Description: Retrieve detailed information for a specific leave requests.
scope: leaveRequest:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"rejectReason": null,
"approverId": null,
"approverName": null,
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T10:00:00"
}
}
5.4 Update Leave Request
Endpoint: PUT /hr/v1/leave-requests/{leaveId}
Description: Update leave request information
scope: leaveRequest:write
Path Parameters:
leaveId (required) - Leave request unique identifier
Request Body: Same fields as Create Leave Request (excluding employeeId), only include fields to update
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-26 09:00",
"toDateTime": "2026-04-28 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T14:00:00"
}
}
5.5 Approve Leave Request
Endpoint: POST /hr/v1/leave-requests/{leaveId}/approve
Description: Approve a pending leave request
scope: leaveRequest:write
Path Parameters:
leaveId (required) - Leave request unique identifier
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"approverId": 2046765589981163500,
"approverName": "Admin User",
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T15:00:00"
}
}
5.6 Reject Leave Request
Endpoint: POST /hr/v1/leave-requests/{leaveId}/reject
Description: Reject a pending leave request
scope: leaveRequest:write
Path Parameters:
leaveId (required) - Leave request unique identifier
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| rejectReason | String | Reason for rejection |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"approverId": 2046765589981163500,
"approverName": "Admin User",
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T15:00:00"
}
}
5.7 Delete Leave Request
Endpoint: DELETE /hr/v1/leave-requests/{leaveId}
Description: Delete a leave request record
scope: leaveRequest:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
6. POSITION MANAGEMENT APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token in Authorization header
6.1 Get Position List
Endpoint: GET /hr/v1/positions
Description: Retrieve paginated list of positions
scope: position:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"positionId": 1,
"positionCode": "ENG-001",
"positionName": "Software Engineer",
"responsibilities": "Develop and maintain software systems",
"minimumSalary": 50000.0,
"maximumSalary": 100000.0,
"currency": "AUD",
"remarks": "Remote work available",
"createdDate": "2026-01-01T10:00:00",
"updatedDate": "2026-01-01T10:00:00"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
6.2 Create Position
Endpoint: POST /hr/v1/positions
Description: Create a new position record in the system
scope: position:write
Request Body (JSON):
{
"positionCode": "ENG-001",
"positionName": "Software Engineer",
"responsibilities": "Develop and maintain software systems",
"minimumSalary": 50000.0,
"maximumSalary": 100000.0,
"currency": "AUD",
"remarks": "Remote work available"
}
Required Fields:
positionName, responsibilities
All Fields:
| Parameter | Type | Description |
|---|---|---|
| positionCode | String | Position code (max: 50 chars) |
| positionName | String | Position name (max: 100 chars) - Required |
| responsibilities | String | Job responsibilities (max: 2000 chars) - Required |
| minimumSalary | Decimal | Minimum salary (>= 0) |
| maximumSalary | Decimal | Maximum salary (>= 0) |
| currency | String | Currency code (e.g. AUD) |
| remarks | String | Additional remarks (max: 500 chars) |
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"positionId": 1,
"positionCode": "ENG-001",
"positionName": "Software Engineer",
"responsibilities": "Develop and maintain software systems",
"minimumSalary": 50000.0,
"maximumSalary": 100000.0,
"currency": "AUD",
"remarks": "Remote work available",
"createdDate": "2026-04-24T10:00:00",
"updatedDate": "2026-04-24T10:00:00"
}
}
6.3 Get Position Details
Endpoint: GET /hr/v1/positions/{positionId}
Description: Retrieve detailed information for a specific position
scope: position:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"positionId": 1,
"positionCode": "ENG-001",
"positionName": "Software Engineer",
"responsibilities": "Develop and maintain software systems",
"minimumSalary": 50000.0,
"maximumSalary": 100000.0,
"currency": "AUD",
"remarks": "Remote work available",
"createdDate": "2026-01-01T10:00:00",
"updatedDate": "2026-01-01T10:00:00"
}
}
6.4 Update Position
Endpoint: PUT /hr/v1/positions/{positionId}
Description: Update position information. Returns the complete updated position record.
scope: position:write
Request Body: Same fields as Create Position, only include fields to update
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"positionId": 1,
"positionCode": "ENG-001",
"positionName": "Senior Software Engineer",
"responsibilities": "Lead development and code reviews",
"minimumSalary": 70000.0,
"maximumSalary": 120000.0,
"currency": "AUD",
"remarks": "Hybrid work model",
"createdDate": "2026-01-01T10:00:00",
"updatedDate": "2026-04-24T14:00:00"
}
}
6.5 Delete Position
Endpoint: DELETE /hr/v1/positions/{positionId}
Description: Delete a position record
scope: position:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
7. JOB LISTINGS APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token in Authorization header
7.1 Get Job Listings List
Endpoint: GET /hr/v1/job-listings
Description: Retrieve paginated list of job listings
scope: jobListings:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
| status | integer | Status filter: 0=Discontinued, 1=Published |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"id": "abc123",
"title": "Senior Software Engineer",
"employmentType": 3,
"location": "Sydney, NSW",
"currency": "AUD",
"payMin": 80000,
"payMax": 120000,
"salaryType": 5,
"payType": 2,
"showPay": true,
"status": 1
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
7.2 Create Job Listing
Endpoint: POST /hr/v1/job-listings
Description: Create a new job listing record in the system
scope: jobListings:write
Request Body (JSON):
{
"title": "Senior Software Engineer",
"employmentType": 3,
"contentBody": "We are looking for...",
"contentFormatting": "html",
"location": "Sydney, NSW",
"currency": "AUD",
"payMin": 80000,
"payMax": 120000,
"salaryType": 5,
"payType": 2,
"showPay": true,
"showExperience": 3,
"status": 1,
"questions": [
{
"questionMsg": "What is your expected salary?",
"questionType": 1,
"isAnswerVideo": false,
"questionIndex": 1
}
]
}
Required Fields:
title, employmentType
All Fields:
| Parameter | Type | Description |
|---|---|---|
| title | String | Job listing title (max: 200 chars) - Required |
| employmentType | Integer | 1=Casual, 2=Part time, 3=Full time - Required |
| contentBody | String | Job description content |
| contentFormatting | String | Content format: text or html |
| location | String | Job location (max: 200 chars) |
| currency | String | Pay currency (max: 10 chars) |
| payMin | Decimal | Minimum pay amount (>= 0) |
| payMax | Decimal | Maximum pay amount (>= 0) |
| salaryType | Integer | 1=hourly, 2=daily, 3=weekly, 4=monthly, 5=annual |
| payType | Integer | 1=Exact amount, 2=Pay range |
| showPay | Boolean | Whether to show pay on listing |
| showExperience | Integer | 0=no requirement, other=years of experience |
| status | Integer | 0=Discontinued, 1=Published |
| questions | Array | Screening questions (see Question Object below) |
Question Object Fields:
| Parameter | Type | Description |
|---|---|---|
| questionMsg | String | Question text (max: 500 chars) - Required |
| questionType | Integer | 1=Short answer, 2=Yes/No, 3=Single select - Required |
| answerOptions | String | Comma-separated options (for Single select type) |
| isAnswerVideo | Boolean | Whether video answer is required |
| questionIndex | Integer | Question display order index |
Success Response (201 Created):
{
"code": 201,
"msg": "Job listing created successfully",
"data": {
"id": "abc123",
"title": "Senior Software Engineer",
"employmentType": 3,
"location": "Sydney, NSW",
"currency": "AUD",
"payMin": 80000,
"payMax": 120000,
"salaryType": 5,
"payType": 2,
"showPay": true,
"status": 1,
"questions": []
}
}
7.3 Get Job Listing Details
Endpoint: GET /hr/v1/job-listings/{id}
Description: Retrieve detailed information for a specific job listing
scope: jobListings:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"id": "abc123",
"title": "Senior Software Engineer",
"employmentType": 3,
"contentBody": "We are looking for...",
"contentFormatting": "html",
"location": "Sydney, NSW",
"currency": "AUD",
"payMin": 80000,
"payMax": 120000,
"salaryType": 5,
"payType": 2,
"showPay": true,
"showExperience": 3,
"status": 1,
"questions": []
}
}
7.4 Update Job Listing
Endpoint: PUT /hr/v1/job-listings/{id}
Description: Update job listing information. Returns the complete updated job listing record.
scope: jobListings:write
Request Body: Same fields as Create Job Listing, only include fields to update. Question objects require id field (UUID) for updates.
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"id": "abc123",
"title": "Senior Software Engineer (Updated)",
"employmentType": 3,
"status": 1
}
}
7.5 Delete Job Listing
Endpoint: DELETE /hr/v1/job-listings/{id}
Description: Delete a job listing record
scope: jobListings:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
8. HOLIDAY ENTITLEMENTS APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token in Authorization header
8.1 Get Holiday Entitlements List
Endpoint: GET /hr/v1/holidays
Description: Retrieve paginated list of holiday entitlements for an employee
scope: holidays:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"empleHolidayId": 1,
"employeeId": 123456789,
"holidayName": "Annual Leave",
"holidayType": "1",
"fromDate": "2026-01-01",
"toDate": "2026-12-31",
"createdDate": "2026-04-27T10:00:00",
"updatedDate": "2026-04-27T10:00:00"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
8.2 Create Holiday Entitlement
Endpoint: POST /hr/v1/holidays
Description: Create a new holiday entitlement record for an employee
scope: holiday:write
Request Body (JSON):
{
"employeeId": 123456789,
"holidayName": "Annual Leave",
"holidayType": "1",
"fromDate": "2026-01-01",
"toDate": "2026-12-31"
}
Required Fields:
employeeId, holidayName, holidayType, fromDate, toDate
All Fields:
| Parameter | Type | Description |
|---|---|---|
| employeeId | Long | Employee ID - Required |
| holidayName | String | Holiday entitlement name (max: 100 chars) - Required |
| holidayType | String | Holiday type: 1=Public Holidays, 2=Private holidays, 3=Company holidays - Required |
| fromDate | String | Start date (yyyy-MM-dd format) - Required |
| toDate | String | End date (yyyy-MM-dd format) - Required |
| employeeId | Long | Employee ID - Required |
| holidayName | String | Holiday entitlement name (max: 100 chars) - Required |
Success Response (201 Created):
{
"code": 201,
"msg": "Job listing created successfully",
"data": {
"empleHolidayId": 1,
"employeeId": 123456789,
"holidayName": "Annual Leave",
"holidayType": "1",
"fromDate": "2026-01-01",
"toDate": "2026-12-31",
"createdDate": "2026-04-27T10:00:00",
"updatedDate": "2026-04-27T10:00:00"
}
}
8.3 Get Holiday Entitlement Details
Endpoint: GET /hr/v1/holidays/{id}
Description: Retrieve detailed information for a specific holiday entitlement
scope: holiday:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"empleHolidayId": 1,
"employeeId": 123456789,
"holidayName": "Annual Leave",
"holidayType": "1",
"fromDate": "2026-01-01",
"toDate": "2026-12-31",
"createdDate": "2026-04-27T10:00:00",
"updatedDate": "2026-04-27T10:00:00"
}
}
8.4 Update Holiday Entitlement
Endpoint: PUT /hr/v1/holidays/{id}
Description: Update holiday entitlement information. Returns the complete updated record.
scope: holiday:write
Request Body: Same fields as Create Holiday Entitlement, only include fields to update. Question objects require id field (UUID) for updates.
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"empleHolidayId": 1,
"employeeId": 123456789,
"holidayName": "Annual Leave",
"holidayType": "1",
"fromDate": "2026-01-01",
"toDate": "2026-12-31",
"createdDate": "2026-04-27T10:00:00",
"updatedDate": "2026-04-27T10:00:00"
}
}
8.5 Delete Holiday Entitlement
Endpoint: DELETE /hr/v1/holidays/{id}
Description: Delete a holiday entitlement record
scope: holiday:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
9. DEPARTMENT MANAGEMENT APIs
Authentication Required: All endpoints require valid OAuth 2.0 access token.
9.1 Get Department List
Endpoint: GET /hr/v1/departments
Description: Retrieve paginated list of departments.
Scope: department:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
| X-Enterprise-Id | header | Enterprise ID (required for client_credentials) |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"deptId": 1,
"deptName": "Engineering",
"orderNum": 1,
"leader": 1001,
"leaderName": "John Smith",
"status": "0",
"empNum": 15
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 5,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
9.2 Create Department
Endpoint: POST /hr/v1/departments
Description: Create a new department in the system.
Scope: department:write
Required Fields: deptName, leader
Request Body (JSON):
{
"deptName": "Engineering",
"leader": 1001,
"orderNum": 1,
"status": "0",
"description": "Responsible for software development",
"employeeIds": [1001, 1002, 1003]
}
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"deptId": 1,
"deptName": "Engineering",
"leader": 1001,
"status": "0"
}
}
9.3 Get Department Details
Endpoint: GET /hr/v1/departments/{deptId}
Description: Retrieve detailed information for a specific department.
Scope: department:read
Path Parameters:
| Parameter | Description |
|---|---|
| deptId | Department ID (integer) |
9.4 Update Department
Endpoint: PUT /hr/v1/departments/{deptId}
Description: Update department information.
Scope: department:write
Request Body fields: deptName, orderNum, leader, status, description, employeeIds (replaces existing).
9.5 Delete Department
Endpoint: DELETE /hr/v1/departments/{deptId}
Description: Delete a department record.
Scope: department:admin
Success Response (200 OK) on successful deletion.
10. ROLE MANAGEMENT APIs
10.1 Get Role List
Endpoint: GET /hr/v1/roles
Description: Retrieve paginated list of roles.
Scope: role:read
Query Parameters: page (default: 1), size (max: 100, default: 20).
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"roleId": 1,
"roleName": "HR Manager",
"roleKey": "hr_manager",
"status": "0",
"menuIds": [1, 2, 3],
"roleSort": 1,
"createdDate": "2025-01-01T00:00:00",
"updatedDate": "2025-06-01T00:00:00"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
10.2 Create Role
Endpoint: POST /hr/v1/roles
Description: Create a new role record.
Scope: role:write
Required Fields: roleName, roleKey
Request Body (JSON):
{
"roleName": "HR Manager",
"roleKey": "hr_manager",
"status": "0",
"menuIds": [1, 2, 3],
"remarks": "HR management role"
}
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"roleId": 1,
"roleName": "HR Manager",
"roleKey": "hr_manager",
"status": "0"
}
}
10.3 Get Role Details
Endpoint: GET /hr/v1/roles/{roleId}
Description: Retrieve detailed information for a specific role.
Scope: role:read
10.4 Update Role
Endpoint: PUT /hr/v1/roles/{roleId}
Description: Update role information.
Scope: role:write
Request Body fields: roleName, roleKey, status (0=Normal, 1=Disabled), menuIds, remarks.
10.5 Delete Role
Endpoint: DELETE /hr/v1/roles/{roleId}
Description: Delete a role record.
Scope: role:admin
11. POLICY MANAGEMENT APIs
11.1 Get Policy List
Endpoint: GET /hr/v1/policies
Description: Retrieve paginated list of policies.
Scope: policy:read
Query Parameters: page (default: 1), size (max: 100, default: 20).
11.2 Create Policy
Endpoint: POST /hr/v1/policies
Description: Create a new policy. Supports both JSON body and multipart/form-data (with file upload).
Scope: policy:write
Required Fields: title
Request Body (JSON):
{
"title": "Code of Conduct Policy",
"deptId": 1,
"audience": "1",
"deptIds": [1, 2, 3],
"employeeIds": [100, 101, 102],
"attachmentUrl": "https://minio.example.com/bucket/policy.pdf",
"effectiveDate": "2026-01-01",
"acknowledgementDeadline": "2026-12-31",
"mandatoryAcknowledgement": true,
"resetAcknowledgement": false
}
Audience type: 1=Global, 2=Department, 3=Specific employees.
For multipart upload, pass file as form-data field and other fields as query parameters.
Success Response (201 Created):
{
"success": true,
"statusCode": 201,
"data": {
"policyId": 1,
"title": "Code of Conduct Policy",
"status": "DRAFT",
"audience": "1",
"audienceLabel": "Global",
"mandatoryAcknowledgement": true
}
}
11.3 Get Policy Details
Endpoint: GET /hr/v1/policies/{policyId}
Description: Retrieve policy details by ID.
Scope: policy:read
11.4 Update Policy
Endpoint: PUT /hr/v1/policies/{policyId}
Description: Update policy via JSON body or multipart/form-data.
Scope: policy:write
Request Body fields: title, audience, deptIds, employeeIds, attachmentUrl, effectiveDate, acknowledgementDeadline, mandatoryAcknowledgement, resetAcknowledgement, status (DRAFT/ACTIVE/ARCHIVED).
11.5 ARCHIVED Policy
Endpoint: POST /hr/v1/policies/{policyId}/archived
Description: Change policy status to ARCHIVED.
Scope: policy:write
Success Response (200 OK) with updated policy data.
11.6 Delete Policy
Endpoint: DELETE /hr/v1/policies/{policyId}
Description: Delete a policy and all its assignments.
Scope: policy:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
12. DOCUMENT MANAGEMENT APIs
12.1 Get Document List
Endpoint: GET /hr/v1/documents
Description: Retrieve paginated list of documents.
Scope: document:read
Query Parameters: page (default: 1), size (max: 100, default: 20).
12.2 Create Document
Endpoint: POST /hr/v1/documents
Description: Create a new document. Supports JSON body or multipart/form-data.
Scope: document:write
Required Fields (JSON): employeeId, documentName
Request Body (JSON):
{
"documentId": 1654546752552,
"employeeId": 1642343324555,
"documentName": "Employment Contract",
"fileUrl": "https://storage.example.com/contract.pdf",
"description": "Annual employment contract",
"status": "1",
"externalId": "4234",
"expiresAt": "2027-12-31",
"invitees": [
{ "sharedToEmployeeId": 123, "permissionType": "2" }
]
}
Note:
fileUrl: External temporary file URL. When provided, server will download the file and upload to MinIO. Takes priority over filePath.
permissionType: 1=READ, 2=DOWNLOAD
status: 0=disabled, 1=enabled
externalId: External system identifier
expiresAt: Document expiry date (yyyy-MM-dd)
12.3 Get Document Details
Endpoint: GET /hr/v1/documents/{documentId}
Description: Retrieve document with full invitee list.
Scope: document:read
12.4 Update Document
Endpoint: PUT /hr/v1/documents/{documentId}
Description: Update document information.
Scope: document:write
Request Body fields: documentName, fileUrl, description, status, expiresAt, invitees.
12.5 Delete Document
Endpoint: DELETE /hr/v1/documents/{documentId}
Description: Delete a document record and all its shares.
Scope: document:admin
Success Response (200 OK):
{
"success": true,
"statusCode": 200
}
13. EMPLOYEE CONTRACT APIs
13.1 Get Contract List
Endpoint: GET /hr/v1/contracts
Description: Retrieve paginated list of employee contracts.
Scope: contract:read
Query Parameters: page (default: 1), size (max: 100, default: 20).
13.2 Get Expired Contracts
Endpoint: GET /hr/v1/contracts/expired
Description: Retrieve paginated list of expired contracts.
Scope: contract:read
13.3 Create Contract
Endpoint: POST /hr/v1/contracts
Description: Create a new employee contract.
Scope: contract:write
Required Fields: employeeId, contractStartTime, contractEndTime
Request Body (JSON):
{
"employeeId": 1001,
"templateId": 5,
"position": "Engineer",
"contractName": "EMP-2026-001",
"contractType": "2",
"contractStartTime": "2026-01-01T00:00:00",
"contractEndTime": "2027-01-01T00:00:00",
"accessory": "https://storage.example.com/contract.pdf",
"isRenewal": "1"
}
contractType: 1=Paper, 2=Electronic | isRenewal: 1=No, 2=Yes
13.4 Get Contract by ID
Endpoint: GET /hr/v1/contracts/{id}
Description: Retrieve a specific employee contract.
Scope: contract:read
13.5 Update Contract
Endpoint: PUT /hr/v1/contracts/{id}
Description: Update employee contract.
Scope: contract:write
Request Body fields: templateId, position, contractName, contractType, contractStartTime, contractEndTime, signStatu (1=Pending, 2=Signed), isMaturity (0=No, 1=Yes), accessory, signDate.
13.6 Renew Contract
Endpoint: POST /hr/v1/contracts/{id}/renew
Description: Creates a new contract as a renewal of the specified contract.
Scope: contract:write
Required Fields: templateId, contractStartTime, contractEndTime
Request Body (JSON):
{
"templateId": 5,
"contractType": "2",
"contractStartTime": "2027-01-01T00:00:00",
"contractEndTime": "2028-01-01T00:00:00",
"accessory": "https://storage.example.com/renewed-contract.pdf",
"isRenewal": "2"
}
13.7 Delete Contract
Endpoint: DELETE /hr/v1/contracts/{id}
Description: Delete an employee contract record.
Scope: contract:admin
14. CONTRACT TEMPLATE APIs
14.1 Get Template List
Endpoint: GET /hr/v1/contracts/templates
Description: Retrieve paginated list of contract templates.
Scope: contractTemplate:read
Query Parameters: page (default: 1), size (max: 100, default: 20).
14.2 Create Template
Endpoint: POST /hr/v1/contracts/templates
Description: Create a new contract template.
Scope: contractTemplate:write
Required Fields: templateName
Request Body (JSON):
{
"templateName": "Standard Employment Contract",
"templateContent": "<p>This agreement...</p>",
"status": "0"
}
templateContent is an HTML string. status: 0=Normal, 1=Deactivated.
14.3 Get Template by ID
Endpoint: GET /hr/v1/contracts/templates/{templateId}
Description: Retrieve a specific contract template.
Scope: contractTemplate:read
14.4 Update Template
Endpoint: PUT /hr/v1/contracts/templates/{templateId}
Description: Update contract template.
Scope: contractTemplate:write
Required Fields: templateName. Other fields: templateContent (HTML), status.
14.5 Delete Template
Endpoint: DELETE /hr/v1/contracts/templates/{templateId}
Description: Delete a contract template record.
Scope: contractTemplate:admin
15. COMPANY SETTINGS APIs
15.1 Get Company Settings
Endpoint: GET /hr/v1/company-settings
Description: Retrieve company settings including security and working hours.
Scope: companySettings:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"enterpriseId": "ent_xxx",
"securitySettings": {
"minPasswordLength": 8,
"requireNumbers": true,
"requireUppercase": true,
"requireSpecialChars": true,
"enable2fa": false,
"sessionTimeoutMinutes": 30,
"maxFailedAttempts": 5
},
"workingHours": {
"defaultStartTime": "09:00:00",
"defaultEndTime": "18:00:00",
"gracePeriod": 15,
"enableOvertime": "1",
"maximumOvertime": 120
}
}
}
15.2 Update Company Settings
Endpoint: PUT /hr/v1/company-settings
Description: Update company settings including security and working hours.
Scope: companySettings:write
Request Body (JSON):
{
"securitySettings": {
"minPasswordLength": 8,
"requireNumbers": true,
"requireUppercase": true,
"requireSpecialChars": true,
"enable2fa": false,
"sessionTimeoutMinutes": 30,
"maxFailedAttempts": 5
},
"workingHours": {
"defaultStartTime": "09:00:00",
"defaultEndTime": "18:00:00",
"gracePeriod": 15,
"enableOvertime": "1",
"maximumOvertime": 120
}
}
enableOvertime: 1=Yes, 2=No | gracePeriod: 0-60 minutes | sessionTimeoutMinutes: 5-480
16. FILE UPLOAD API
16.1 Upload File
Endpoint: POST /hr/v1/files
Description: Upload a file to MinIO storage. Returns file URL and metadata.
Scope: file:write
Request: multipart/form-data with 'file' field (max size: 50MB).
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"fileName": "document.pdf",
"fileUrl": "https://minio.example.com/bucket/path/document.pdf",
"fileSize": 102400,
"fileType": "application/pdf"
}
}
The returned fileUrl can be used as attachmentUrl when creating policies or as filePath when creating documents.
17. MENU MANAGEMENT APIs
17.1 Get Menu List
Endpoint: GET /hr/v1/menus
Description: Retrieve list of all menus.
Scope: role:read
17.2 Get Menu Tree
Endpoint: GET /hr/v1/menus/tree
Description: Retrieve hierarchical menu tree structure.
Scope: role:read
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"menuId": 1,
"menuName": "Dashboard",
"parentId": 0,
"orderNum": 1,
"path": "/dashboard",
"menuType": "C",
"visible": "0",
"status": "0",
"perms": "dashboard:list",
"children": []
}
]
}
menuType: M=Directory, C=Menu, F=Button | visible: 0=Show, 1=Hide | status: 0=Normal, 1=Disabled
17.3 Get Menu by ID
Endpoint: GET /hr/v1/menus/{menuId}
Description: Retrieve a specific menu item.
Scope: role:read
17. COMPANY PROVISION API
Note: This is an internal API for ShiftCare to auto-provision new HR company instances. It requires a client_credentials M2M token with company:admin scope.
This API does not transmit X-Enterprise-Id
17.1 Auto-Provision HR Company Instance
Endpoint: POST /hr/v1/companies/provision
Description: Creates a new HR company, initializes system roles, creates the initial admin account, and binds the Shiftcare credentials.Triggered by ShiftCare on trial creation or plan purchase with HR add-on.
Scope: company:admin (client_credentials M2M token only)
Required Fields: companyName, contactEmail, adminFullName, adminEmail, adminUsername
Request Body (JSON):
{
"companyName": "Acme Corp",
"industryType": "healthcare",
"country": "AU",
"timeZone": "Australia/Sydney",
"contactEmail": "admin@acme.com",
"currency": "AUD",
"phone": "0400000000",
"phoneCode": "+61",
"logoUrl": "https://cdn.shiftcare.com/logos/acme.png",
"planId": "trial",
"adminFullName": "John Smith",
"adminEmail": "john@acme.com",
"adminUsername": "john.smith",
"encryptedApiCredentials": {
"iv": "MXc3JZLahWmB+FSO",
"ciphertext": "0KQlNzQ3Ufj+1cVSiZZ50C4IYbCdGOPTBOpCGBUFopR3fJ2ioouOz9mHHmLY27qc09Jk4MmP/M6pPPT5wH4On+dcgUlzFurZBVO2cdWNyF/DD7Ml6mS6koHxiVS23F42NQZOHQ=="
}
}
Success Response (201 Created):
{
"enterpriseId": "1234567890123456789",
"companyName": "Acme Corp",
"createdFrom": "Shiftcare",
"adminUsername": "john.smith",
"adminEmail": "john@acme.com",
"status": "provisioned",
"createdAt": "2026-04-27T10:00:00Z"
}
Error Responses:
| HTTP Code | Description |
|---|---|
| 400 | Invalid request - validation errors |
| 401 | Unauthorized - invalid or expired token |
| 403 | Forbidden - insufficient scope or user JWT not allowed |
| 409 | Conflict - company with same email already exists |
| 500 | Internal server error |
18. REPORT API
18.1 Get Emergency Contacts Report List
Endpoint: GET /hr/v1/reports/emergency-contacts
Description: Retrieve paginated list of employee emergency contacts.
Scope: employee:read
Query Parameters: page (default: 1), size (max: 100, default: 20).
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"leaveId": 2001,
"employeeId": 2046765589981163521,
"employeeName": "Jane Doe",
"leaveType": "1",
"fromDateTime": "2026-04-25 09:00",
"toDateTime": "2026-04-27 18:00",
"notes": "Family vacation",
"totalDays": 3,
"status": 1,
"rejectReason": null,
"approverId": null,
"approverName": null,
"createDate": "2026-04-22T10:00:00",
"updatedDate": "2026-04-22T10:00:00"
}
],
"pagination": {
"currentPage": 1,
"pageSize": 20,
"totalItems": 1,
"totalPages": 1,
"hasNextPage": false,
"hasPreviousPage": false
}
}
18.2 Get Leave Report Statistics
Endpoint: GET /hr/v1/reports/leave-statistics
Description: Retrieve leave statistics summary.
Scope: leaveRequest:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| leaveType | String | Leave type code (1-13, see section 4.3) |
| deptId | Long | Department ID filter |
| startDate | String | Start date filter (YYYY-MM-DD) |
| endDate | String | End date filter (YYYY-MM-DD) |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": {
"totalLeaveLiability": 0.0,
"totalAccruedThisPeriod": 0,
"totalTakenThisPeriod": 23
}
}
18.3 Get Leave Report List
Endpoint: GET /hr/v1/reports/leave-report-list
Description: Retrieve paginated leave report list with filters.
Scope: leaveRequest:read
Query Parameters:
| Parameter | Type | Description |
|---|---|---|
| page | integer | Page number (default: 1) |
| size | integer | Page size (max: 100, default: 20) |
| leaveType | String | Leave type code (1-13, see section 4.3) |
| deptId | Long | Department ID filter |
| startDate | String | Start date filter (YYYY-MM-DD) |
| endDate | String | End date filter (YYYY-MM-DD) |
Success Response (200 OK):
{
"success": true,
"statusCode": 200,
"data": [
{
"employeeId": 1980092118274641922,
"employeeName": "AFrank11 AAFrank11",
"deptName": "Test",
"leaveType": "13",
"opening": 1,
"taken": 1
}
],
"pagination": {
"currentPage": 1,
"pageSize": 3,
"totalItems": 96,
"totalPages": 32,
"hasNextPage": true,
"hasPreviousPage": false
}
}
18. ERROR HANDLING
18.1 Standard Error Response
All error responses follow a consistent format:
{
"success": false,
"statusCode": 400,
"errorMessage": "Missing required field: email",
}
18.2 HTTP Status Codes
| Code | Status | Description |
|---|---|---|
| 200 | OK | Request succeeded |
| 201 | Created | Resource created successfully |
| 400 | Bad Request | Invalid request format or missing required fields |
| 401 | Unauthorized | Missing, invalid, or expired access token |
| 403 | Forbidden | Insufficient permissions for requested operation |
| 404 | Not Found | Resource not found |
| 429 | Too Many Requests | Rate limit exceeded (100 req/min per client) |
| 500 | Internal Server Error | Server error - contact support if persists |
18.3 OAuth Error Codes
OAuth 2.0 token endpoint returns specific error codes per RFC 6749:
| Error Code | Description |
|---|---|
| invalid_request | Malformed request (missing parameters, etc.) |
| invalid_client | Invalid client_id or client_secret |
| invalid_grant | Invalid or expired refresh_token |
| unauthorized_client | Client not authorized for this grant type |
| unsupported_grant_type | Grant type not supported |
19. RATE LIMITING & SECURITY
19.1 Rate Limits
API requests are rate limited to ensure system stability:
| Endpoint Type | Limit |
|---|---|
| OAuth Token Endpoint | 10 requests per minute per IP address |
| General API Endpoints | 100 requests per minute per client_id |
Rate Limit Headers:
Response headers include rate limit information:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1702387200
When rate limit is exceeded:
HTTP/1.1 429 Too Many Requests
Retry-After: 60
{
"success": false,
"statusCode": 429,
"errorMessage": "API rate limit exceeded",
}
19.2 Security Requirements
HTTPS Required: All API calls must use HTTPS (TLS 1.2 minimum)
Token Storage: Store client_secret securely, never expose in client-side code
Token Transmission: Only send tokens in Authorization header, never in URL
Error Handling: Don't log sensitive information (tokens, secrets) in error messages
20. INTEGRATION CHECKLIST FOR YOUR COMPANY
Required Actions:
20.1 Pre-Integration
Obtain OAuth 2.0 credentials (client_id and client_secret) from HR Tool
Confirm external_id mapping strategy for employees
Set up testing environment access
20.2 Implementation Tasks
Implement OAuth 2.0 client credentials flow
Implement token refresh logic with proper rotation
Implement JWT signature verification using public keys
Build employee sync logic (create, update, delete)
Implement error handling and retry logic
Handle rate limiting with exponential backoff
20.3 Testing Requirements
Test OAuth token acquisition in testing environment
Test token refresh and rotation
Test employee CRUD operations
Test error scenarios (invalid tokens, rate limits, etc.)
Load testing to verify rate limits
20.4 Production Readiness
Complete security review
Set up monitoring and alerting
Configure production credentials
Document integration for internal teams
Plan rollout and migration strategy
APPENDIX A: QUICK REFERENCE
A.1 Key Endpoints Summary
| Method | Endpoint | Description |
|---|---|---|
| POST | /oauth2/token | Get access token |
| GET | /hr/v1/employees | List employees |
| POST | /hr/v1/employees | Create employee |
| PUT | /hr/v1/employees/{id} | Update employee |
| DELETE | /hr/v1/employees/{id} | Delete employee |
| PUT | /hr/v1/employees/{id}/offboard | Offboard employee |
| PUT | /hr/v1/employees/{id}/restore | Restore employee |
| GET | /hr/v1/employees/{id} | Get employee Details |
| GET | /hr/v1/leave-types | List leave types |
| POST | /hr/v1/leave-types | Create leave type |
| GET | /hr/v1/leave-types/{id} | Get leave type details |
| PUT | /hr/v1/leave-types/{id} | Update leave type |
| DELETE | /hr/v1/leave-types/{id} | Delete leave type |
| GET | /hr/v1/leave-requests | List leave requests |
| POST | /hr/v1/leave-requests | Create leave request |
| GET | /hr/v1/leave-requests/{id} | Get leave request details |
| PUT | /hr/v1/leave-requests/{id} | Update leave request |
| POST | /hr/v1/leave-requests/{id}/approve | Approve leave request |
| POST | /hr/v1/leave-requests/{id}/reject | Reject leave request |
| DELETE | /hr/v1/leave-requests/{id} | Delete leave request |
| GET | /hr/v1/positions | List positions |
| POST | /hr/v1/positions | Create position |
| GET | /hr/v1/positions/{id} | Get position details |
| PUT | /hr/v1/positions/{id} | Update position |
| DELETE | /hr/v1/positions/{id} | Delete position |
| GET | /hr/v1/job-listings | List job listings |
| POST | /hr/v1/job-listings | Create job listing |
| GET | /hr/v1/job-listings/{id} | Get job listing details |
| PUT | /hr/v1/job-listings/{id} | Update job listing |
| DELETE | /hr/v1/job-listings/{id} | Delete job listing |
| GET | /hr/v1/departments | List departments |
| POST | /hr/v1/departments | Create department |
| GET | /hr/v1/departments/{deptId} | Get department details |
| PUT | /hr/v1/departments/{deptId} | Update department |
| DELETE | /hr/v1/departments/{deptId} | Delete department |
| GET | /hr/v1/roles | List roles |
| POST | /hr/v1/roles | Create role |
| GET | /hr/v1/roles/{roleId} | Get role details |
| PUT | /hr/v1/roles/{roleId} | Update role |
| DELETE | /hr/v1/roles/{roleId} | Delete role |
| GET | /hr/v1/policies | List policies |
| POST | /hr/v1/policies | Create policy |
| GET | /hr/v1/policies/{policyId} | Get policy details |
| PUT | /hr/v1/policies/{policyId} | Update policy |
| POST | /hr/v1/policies/{policyId}/publish | Publish policy |
| DELETE | /hr/v1/policies/{policyId} | Delete policy |
| GET | /hr/v1/documents | List documents |
| POST | /hr/v1/documents | Create document |
| GET | /hr/v1/documents/{documentId} | Get document details |
| PUT | /hr/v1/documents/{documentId} | Update document |
| DELETE | /hr/v1/documents/{documentId} | Delete document |
| GET | /hr/v1/contracts | List employee contracts |
| POST | /hr/v1/contracts | Create employee contract |
| GET | /hr/v1/contracts/expired | Get expired contracts |
| GET | /hr/v1/contracts/{id} | Get contract by ID |
| PUT | /hr/v1/contracts/{id} | Update contract |
| POST | /hr/v1/contracts/{id}/renew | Renew contract |
| DELETE | /hr/v1/contracts/{id} | Delete contract |
| GET | /hr/v1/contracts/templates | List contract templates |
| POST | /hr/v1/contracts/templates | Create contract template |
| GET | /hr/v1/contracts/templates/{templateId} | Get template by ID |
| PUT | /hr/v1/contracts/templates/{templateId} | Update template |
| DELETE | /hr/v1/contracts/templates/{templateId} | Delete template |
| GET | /hr/v1/company-settings | Get company settings |
| PUT | /hr/v1/company-settings | Update company settings |
| POST | /hr/v1/files | Upload file |
| GET | /hr/v1/menus | List menus |
| GET | /hr/v1/menus/tree | Get menu tree |
| GET | /hr/v1/menus/{menuId} | Get menu by ID |
| POST | /hr/v1/companies/provision | Auto-provision company instance |
| GET | /hr/v1/holidays | List holiday entitlements |
| GET | /hr/v1/holidays/{holidayId} | Get holiday entitlement by ID |
| POST | /hr/v1/holidays | Create holiday entitlement |
| PUT | /hr/v1/holidays/{holidayId} | Update holiday entitlement |
| DELETE | /hr/v1/holidays/{holidayId} | Delete holiday entitlement |
| GET | /hr/v1/reports/emergency-contacts | Get emergency contacts reports |
| GET | /hr/v1/reports/leave-statistics | Retrieve leave statistics summary |
| GET | /hr/v1/reports/leave-report-list | Retrieve paginated leave report list with filters |
A.2 Token Lifetimes
| Token | Lifetime |
|---|---|
| Access Token | 15 minutes |