Purple HRIS API Documentation
Machine-readable OpenAPI 3.0 specification: https://marketplace.moveworks.com/api/purple-suite/hris/openapi.json
The consolidated all-apps document at https://marketplace.moveworks.com/api/purple-suite/openapi.json can be narrowed to this app with ?apps=hris, or combined with other apps comma-separated (e.g. ?apps=hris,itsm).
Overview
Endpoints
POST /api/purple-suite/hris/employees/search
Search HRIS employees by name, email or attributes
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
querystring — Free-text search query (tokenized, scored by term overlap). Mutually exclusive with framed fields.namestring — Full or partial person name — firstName + lastName substring match (framed search)emailstring — Email address partial match (framed search)departmentstring — Exact department name match (framed search)rolestring — Role/title substring match (framed search)manager_namestring — Manager full name substring — applied as post-filter after framed scoring (framed search)manager_emailstring — Manager email substring — applied as post-filter after framed scoring (framed search)employment_statusstring — Employment status exact match (framed search)
Responses
200- Search results in RecordResult format (top 5 matches by score)
application/jsonresultsarrayarray of:
recordobject — Nested RecordResult envelopeNested RecordResult envelopemeta_infoobjectstructured_entityobjectperson_entityobjectperson_infoobject…
contact_infoobject…
occupation_infoobject…
workplace_infoobject…
scorenumber — Match score between 0 and 1confidencestring — EXACT_MATCH ≥ 0.9, VALID ≥ 0.5, INVALID < 0.5
total_retrievedinteger
500- Internal server error
POST /api/purple-suite/hris/users/search
Search HRIS employees, projected as flat User records
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
querystring — Free-text search query (tokenized, scored by term overlap). Mutually exclusive with framed fields.namestring — Full or partial person name — firstName + lastName substring match (framed search)emailstring — Email address partial match (framed search)departmentstring — Exact department name match (framed search)rolestring — Role/title substring match (framed search)manager_namestring — Manager full name substring — applied as post-filter after framed scoring (framed search)manager_emailstring — Manager email substring — applied as post-filter after framed scoring (framed search)employment_statusstring — Employment status exact match (framed search)
Responses
200- Search results as flat User records (top 5 matches by score)
application/jsonresultsarrayarray of:
record_idstring — Employee idemail_addrstringfull_namestringfirst_namestringlast_namestringdepartmentstringrolestringmanager_emailstringtimezonestringlocationstring
total_retrievedinteger
500- Internal server error
GET /api/purple-suite/hris/employees
List HRIS employee records
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
status | query | string | no | Filter by employment status (exact match). Legacy — prefer $filter. |
department | query | string | no | Filter by department name (exact match). Legacy — prefer $filter. |
firstName | query | string | no | Filter by first name (exact match). Legacy — prefer $filter. |
lastName | query | string | no | Filter by last name (exact match). Legacy — prefer $filter. |
email | query | string | no | Filter by email address (exact match). Legacy — prefer $filter. |
managerId | query | string | no | Filter by manager employee ID (exact match). Legacy — prefer $filter. |
search | query | string | no | Free-text search across firstName, lastName, and email (substring match). Legacy — equivalent to $search. |
Responses
200- Paginated list
application/jsondataarrayarray of:
EmployeeidstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/employees
Create an HRIS employee record
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
Employee
idstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
Responses
201- Created
application/jsonEmployeeidstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
400- Missing required field or invalid status
409- Employee with this email already exists
GET /api/purple-suite/hris/employees/{id}
Get an HRIS employee record by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonEmployeeidstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/employees/{id}
Delete an HRIS employee record
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/employees/{id}
Update an HRIS employee record
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
Employee
idstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
Responses
200- Updated
application/jsonEmployeeidstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
404- Not found
422- State machine violation (e.g. reactivating a terminated employee)
POST /api/purple-suite/hris/employees/{id}/transition
Move an employee through their lifecycle (leave / return / terminate)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json — required
statusstring required — Target status for the transitionreasonstring — Human-readable reason for the transition (appended to status_history)effective_datestring — When the transition takes effect (defaults to now)daysnumber — PTO vacation days to deduct from pto_balance.vacation_days. Only applied when transitioning to on_leave.
Responses
200- Updated employee record
application/jsonEmployeeidstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
400- Invalid status value
404- Employee not found
422- Transition not allowed by state machine rules
PATCH /api/purple-suite/hris/employees/{id}/pto-balance
Set an employee's PTO day balances
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json — required
vacation_daysnumber — New vacation day balance. Omit to keep current value.sick_daysnumber — New sick day balance. Omit to keep current value.
Responses
200- Updated employee record with new pto_balance
application/jsonEmployeeidstringfirstNamestring required — Employee first name. Alias accepted on create/update: first_namelastNamestring required — Employee last name. Alias accepted on create/update: last_nameemailstring requireddepartmentstring — Department name. Must match an existing department. Alias accepted on create: department_idtitlestringstatusstring — Employment status. On PATCH also accepts 'suspended'. Use the /transition endpoint for lifecycle transitions.startDatestring — Employment start date. Alias accepted on create: hire_datesalarynumbermanagerIdstring — ID of the manager employee. Alias accepted on create: manager_idphonestringlocationstring — City (leaf of the location hierarchy city ∈ country ∈ region).countrystring — Country (derived from city). Middle level of the location hierarchy; drives HRBP country-level scope.timezonestringcostCenterstringregionstring — Geographic region (derived from location/city). Top level of the location hierarchy; used by HRBP analytics group-by + region scope.job_levelstring — Job level code (IC1–IC6 / M1–M7). Alias accepted on create: level.management_levelstring — Individual Contributor or Managerial.employment_typestring — Worker classification. Drives contingent-headcount analytics.probation_end_datestring — End of probation period; null once past probation. Drives probation-headcount analytics.termination_typestring — Set when status→terminated via /transition.termination_reasonstring — Categorized exit reason (e.g. compensation, career_growth, relocation, performance, retirement).termination_datestring — Effective termination date (mirrors the latest 'terminated' status_history entry).pto_balanceobject — Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.Current PTO balance. Use PATCH /employees/{id}/pto-balance to update directly.vacation_daysnumbersick_daysnumber
status_historyarray — Immutable audit log of status transitions (appended by /transition endpoint).Immutable audit log of status transitions (appended by /transition endpoint).array of:
statusstringreasonstringeffective_datestringrecorded_atstring
skillsarray — Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.Employee skills with proficiency. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/skills.array of:
skillstringproficiencystringlast_updatedstring
reviewsarray — Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.Recent performance reviews. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/reviews.array of:
idstringperiodstringratingstringstrengthsarrayarray of:
string
gapsarrayarray of:
string
reviewer_idstringreviewed_atstring
goalsarray — Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.Current development goals. Settable via PATCH /employees/{id}. Also available at GET /employees/{id}/goals.array of:
idstringdescriptionstringtarget_rolestringtarget_timelinestringstatusstringprogress_pctinteger
generate_related_recordsboolean — CREATE only. When true (or camelCase generateRelatedRecords), seeds 3 timesheets and 2 benefits for the new employee. Not stored.createdAtstringupdatedAtstring
404- Employee not found
GET /api/purple-suite/hris/employees/{id}/skills
Get an employee's skills profile
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Employee skills
application/jsonemployee_idstringskillsarrayarray of:
#/components/schemas/Employee/properties/skills/items
404- Employee not found
GET /api/purple-suite/hris/employees/{id}/reviews
Get an employee's performance review history
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Employee reviews
application/jsonemployee_idstringreviewsarrayarray of:
#/components/schemas/Employee/properties/reviews/items
404- Employee not found
GET /api/purple-suite/hris/employees/{id}/goals
Get an employee's development goals
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Employee goals
application/jsonemployee_idstringgoalsarrayarray of:
#/components/schemas/Employee/properties/goals/items
404- Employee not found
GET /api/purple-suite/hris/departments
List HRIS departments
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
name | query | string | no | Filter by department name (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
Departmentidstringnamestring requiredmanagerstring — Email of the department manager. Aliases accepted on create: managerId, head_employee_idbudgetnumberheadCountinteger — Number of employees in the department. Alias accepted on create: headcount (lowercase)createdAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/departments
Create an HRIS department
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
Department
idstringnamestring requiredmanagerstring — Email of the department manager. Aliases accepted on create: managerId, head_employee_idbudgetnumberheadCountinteger — Number of employees in the department. Alias accepted on create: headcount (lowercase)createdAtstringupdatedAtstring
Responses
201- Created
application/jsonDepartmentidstringnamestring requiredmanagerstring — Email of the department manager. Aliases accepted on create: managerId, head_employee_idbudgetnumberheadCountinteger — Number of employees in the department. Alias accepted on create: headcount (lowercase)createdAtstringupdatedAtstring
GET /api/purple-suite/hris/departments/{id}
Get an HRIS department by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonDepartmentidstringnamestring requiredmanagerstring — Email of the department manager. Aliases accepted on create: managerId, head_employee_idbudgetnumberheadCountinteger — Number of employees in the department. Alias accepted on create: headcount (lowercase)createdAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/departments/{id}
Delete an HRIS department
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/departments/{id}
Edit an HRIS department
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
Department
idstringnamestring requiredmanagerstring — Email of the department manager. Aliases accepted on create: managerId, head_employee_idbudgetnumberheadCountinteger — Number of employees in the department. Alias accepted on create: headcount (lowercase)createdAtstringupdatedAtstring
Responses
200- Updated
application/jsonDepartmentidstringnamestring requiredmanagerstring — Email of the department manager. Aliases accepted on create: managerId, head_employee_idbudgetnumberheadCountinteger — Number of employees in the department. Alias accepted on create: headcount (lowercase)createdAtstringupdatedAtstring
404- Not found
GET /api/purple-suite/hris/pay-runs
List payroll runs
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
status | query | string | no | Filter by pay run status (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
PayRunidstringperiodStartstring — Pay period start date. Alias accepted on create: period_startperiodEndstring — Pay period end date. Alias accepted on create: period_endstatusstring — Pay run status. State machine: draft → processing → completed. Completed runs are locked. Cancelled runs cannot be reactivated.totalAmountnumber — Total gross payroll amount. Alias accepted on create: total_amountemployeeCountinteger — Number of employees included in this run. Alias accepted on create: employee_countrunDatestringentriesarray — Per-employee pay breakdown. Set on create or PATCH.Per-employee pay breakdown. Set on create or PATCH.array of:
employeeIdstringgrossPaynumbernetPaynumber
createdAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/pay-runs
Open a payroll run
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
PayRun
idstringperiodStartstring — Pay period start date. Alias accepted on create: period_startperiodEndstring — Pay period end date. Alias accepted on create: period_endstatusstring — Pay run status. State machine: draft → processing → completed. Completed runs are locked. Cancelled runs cannot be reactivated.totalAmountnumber — Total gross payroll amount. Alias accepted on create: total_amountemployeeCountinteger — Number of employees included in this run. Alias accepted on create: employee_countrunDatestringentriesarray — Per-employee pay breakdown. Set on create or PATCH.Per-employee pay breakdown. Set on create or PATCH.array of:
employeeIdstringgrossPaynumbernetPaynumber
createdAtstringupdatedAtstring
Responses
201- Created
application/jsonPayRunidstringperiodStartstring — Pay period start date. Alias accepted on create: period_startperiodEndstring — Pay period end date. Alias accepted on create: period_endstatusstring — Pay run status. State machine: draft → processing → completed. Completed runs are locked. Cancelled runs cannot be reactivated.totalAmountnumber — Total gross payroll amount. Alias accepted on create: total_amountemployeeCountinteger — Number of employees included in this run. Alias accepted on create: employee_countrunDatestringentriesarray — Per-employee pay breakdown. Set on create or PATCH.Per-employee pay breakdown. Set on create or PATCH.array of:
employeeIdstringgrossPaynumbernetPaynumber
createdAtstringupdatedAtstring
GET /api/purple-suite/hris/pay-runs/{id}
Get a payroll run by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonPayRunidstringperiodStartstring — Pay period start date. Alias accepted on create: period_startperiodEndstring — Pay period end date. Alias accepted on create: period_endstatusstring — Pay run status. State machine: draft → processing → completed. Completed runs are locked. Cancelled runs cannot be reactivated.totalAmountnumber — Total gross payroll amount. Alias accepted on create: total_amountemployeeCountinteger — Number of employees included in this run. Alias accepted on create: employee_countrunDatestringentriesarray — Per-employee pay breakdown. Set on create or PATCH.Per-employee pay breakdown. Set on create or PATCH.array of:
employeeIdstringgrossPaynumbernetPaynumber
createdAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/pay-runs/{id}
Delete a payroll run
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/pay-runs/{id}
Advance or edit a payroll run
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
PayRun
idstringperiodStartstring — Pay period start date. Alias accepted on create: period_startperiodEndstring — Pay period end date. Alias accepted on create: period_endstatusstring — Pay run status. State machine: draft → processing → completed. Completed runs are locked. Cancelled runs cannot be reactivated.totalAmountnumber — Total gross payroll amount. Alias accepted on create: total_amountemployeeCountinteger — Number of employees included in this run. Alias accepted on create: employee_countrunDatestringentriesarray — Per-employee pay breakdown. Set on create or PATCH.Per-employee pay breakdown. Set on create or PATCH.array of:
employeeIdstringgrossPaynumbernetPaynumber
createdAtstringupdatedAtstring
Responses
200- Updated
application/jsonPayRunidstringperiodStartstring — Pay period start date. Alias accepted on create: period_startperiodEndstring — Pay period end date. Alias accepted on create: period_endstatusstring — Pay run status. State machine: draft → processing → completed. Completed runs are locked. Cancelled runs cannot be reactivated.totalAmountnumber — Total gross payroll amount. Alias accepted on create: total_amountemployeeCountinteger — Number of employees included in this run. Alias accepted on create: employee_countrunDatestringentriesarray — Per-employee pay breakdown. Set on create or PATCH.Per-employee pay breakdown. Set on create or PATCH.array of:
employeeIdstringgrossPaynumbernetPaynumber
createdAtstringupdatedAtstring
404- Not found
422- State machine violation (e.g. modifying a completed run, or skipping processing status)
GET /api/purple-suite/hris/timesheets
List employee timesheets
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
employee_id | query | string | no | Filter by employee ID (exact match) |
status | query | string | no | Filter by timesheet status (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
Timesheetidstringemployee_idstringweek_startstringhours_workednumberovertime_hoursnumberstatusstringcreated_atstringupdated_atstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/timesheets
Submit a weekly timesheet
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
Timesheet
idstringemployee_idstringweek_startstringhours_workednumberovertime_hoursnumberstatusstringcreated_atstringupdated_atstring
Responses
201- Created
application/jsonTimesheetidstringemployee_idstringweek_startstringhours_workednumberovertime_hoursnumberstatusstringcreated_atstringupdated_atstring
400- Missing required field or out-of-range hours
404- Employee not found
409- Timesheet already exists for this employee and week
422- Cannot submit timesheet for a terminated employee
GET /api/purple-suite/hris/timesheets/{id}
Get a timesheet by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonTimesheetidstringemployee_idstringweek_startstringhours_workednumberovertime_hoursnumberstatusstringcreated_atstringupdated_atstring
404- Not found
DELETE /api/purple-suite/hris/timesheets/{id}
Delete a timesheet
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/timesheets/{id}
Approve, reject or correct a timesheet
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
Timesheet
idstringemployee_idstringweek_startstringhours_workednumberovertime_hoursnumberstatusstringcreated_atstringupdated_atstring
Responses
200- Updated
application/jsonTimesheetidstringemployee_idstringweek_startstringhours_workednumberovertime_hoursnumberstatusstringcreated_atstringupdated_atstring
404- Not found
GET /api/purple-suite/hris/benefits
List employee benefit enrollments
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
employee_id | query | string | no | Filter by employee ID (exact match) |
type | query | string | no | Filter by benefit type (exact match) |
status | query | string | no | Filter by benefit status (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
Benefitidstringemployee_idstringtypestringplan_namestringstatusstringenrollment_datestringcreated_atstringupdated_atstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/benefits
Enroll an employee in a benefit plan
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
Benefit
idstringemployee_idstringtypestringplan_namestringstatusstringenrollment_datestringcreated_atstringupdated_atstring
Responses
201- Created
application/jsonBenefitidstringemployee_idstringtypestringplan_namestringstatusstringenrollment_datestringcreated_atstringupdated_atstring
400- Missing required field or invalid type
404- Employee not found
422- Employee already has an active benefit of this type
GET /api/purple-suite/hris/benefits/{id}
Get a benefit enrollment by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonBenefitidstringemployee_idstringtypestringplan_namestringstatusstringenrollment_datestringcreated_atstringupdated_atstring
404- Not found
DELETE /api/purple-suite/hris/benefits/{id}
Delete a benefit enrollment
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/benefits/{id}
Change or terminate a benefit enrollment
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
Benefit
idstringemployee_idstringtypestringplan_namestringstatusstringenrollment_datestringcreated_atstringupdated_atstring
Responses
200- Updated
application/jsonBenefitidstringemployee_idstringtypestringplan_namestringstatusstringenrollment_datestringcreated_atstringupdated_atstring
404- Not found
GET /api/purple-suite/hris/review-cycles
List performance review cycles
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
employee_id | query | string | no | Filter by employee ID (exact match) |
status | query | string | no | Filter by review cycle status (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
ReviewCycleidstringnamestringperiodstringstatusstringemployee_idstringmanager_idstringratingstringnotesstringcreated_atstringupdated_atstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/review-cycles
Open a performance review cycle
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
ReviewCycle
idstringnamestringperiodstringstatusstringemployee_idstringmanager_idstringratingstringnotesstringcreated_atstringupdated_atstring
Responses
201- Created
application/jsonReviewCycleidstringnamestringperiodstringstatusstringemployee_idstringmanager_idstringratingstringnotesstringcreated_atstringupdated_atstring
GET /api/purple-suite/hris/review-cycles/{id}
Get a performance review cycle by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonReviewCycleidstringnamestringperiodstringstatusstringemployee_idstringmanager_idstringratingstringnotesstringcreated_atstringupdated_atstring
404- Not found
DELETE /api/purple-suite/hris/review-cycles/{id}
Delete a performance review cycle
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/review-cycles/{id}
Progress or complete a review cycle
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
ReviewCycle
idstringnamestringperiodstringstatusstringemployee_idstringmanager_idstringratingstringnotesstringcreated_atstringupdated_atstring
Responses
200- Updated
application/jsonReviewCycleidstringnamestringperiodstringstatusstringemployee_idstringmanager_idstringratingstringnotesstringcreated_atstringupdated_atstring
404- Not found
GET /api/purple-suite/hris/time-off-requests
List time-off (PTO) requests
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
employee_id | query | string | no | Filter by employee ID (exact match) |
status | query | string | no | Filter by request status (exact match) |
type | query | string | no | Filter by time-off type (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
TimeOffRequestidstringemployee_idstring required — ID of the requesting employee. Alias accepted on create: employeeIdtypestring — Kind of time off. Defaults to 'vacation'.start_datestring required — First day off (inclusive). Alias accepted on create: startDateend_datestring required — Last day off (inclusive). Alias accepted on create: endDatehoursnumber — Total hours requestednotestring — Optional reason / note for the requeststatusstring — Request status. Defaults to 'pending' on create; approve/deny via PATCH.created_atstringupdated_atstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/time-off-requests
Submit a time-off (PTO) request
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
TimeOffRequest
idstringemployee_idstring required — ID of the requesting employee. Alias accepted on create: employeeIdtypestring — Kind of time off. Defaults to 'vacation'.start_datestring required — First day off (inclusive). Alias accepted on create: startDateend_datestring required — Last day off (inclusive). Alias accepted on create: endDatehoursnumber — Total hours requestednotestring — Optional reason / note for the requeststatusstring — Request status. Defaults to 'pending' on create; approve/deny via PATCH.created_atstringupdated_atstring
Responses
201- Created
application/jsonTimeOffRequestidstringemployee_idstring required — ID of the requesting employee. Alias accepted on create: employeeIdtypestring — Kind of time off. Defaults to 'vacation'.start_datestring required — First day off (inclusive). Alias accepted on create: startDateend_datestring required — Last day off (inclusive). Alias accepted on create: endDatehoursnumber — Total hours requestednotestring — Optional reason / note for the requeststatusstring — Request status. Defaults to 'pending' on create; approve/deny via PATCH.created_atstringupdated_atstring
400- Missing required field or invalid type/status
404- Employee not found
GET /api/purple-suite/hris/time-off-requests/{id}
Get a time-off (PTO) request by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonTimeOffRequestidstringemployee_idstring required — ID of the requesting employee. Alias accepted on create: employeeIdtypestring — Kind of time off. Defaults to 'vacation'.start_datestring required — First day off (inclusive). Alias accepted on create: startDateend_datestring required — Last day off (inclusive). Alias accepted on create: endDatehoursnumber — Total hours requestednotestring — Optional reason / note for the requeststatusstring — Request status. Defaults to 'pending' on create; approve/deny via PATCH.created_atstringupdated_atstring
404- Not found
PATCH /api/purple-suite/hris/time-off-requests/{id}
Approve, deny or amend a time-off request
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
TimeOffRequest
idstringemployee_idstring required — ID of the requesting employee. Alias accepted on create: employeeIdtypestring — Kind of time off. Defaults to 'vacation'.start_datestring required — First day off (inclusive). Alias accepted on create: startDateend_datestring required — Last day off (inclusive). Alias accepted on create: endDatehoursnumber — Total hours requestednotestring — Optional reason / note for the requeststatusstring — Request status. Defaults to 'pending' on create; approve/deny via PATCH.created_atstringupdated_atstring
Responses
200- Updated
application/jsonTimeOffRequestidstringemployee_idstring required — ID of the requesting employee. Alias accepted on create: employeeIdtypestring — Kind of time off. Defaults to 'vacation'.start_datestring required — First day off (inclusive). Alias accepted on create: startDateend_datestring required — Last day off (inclusive). Alias accepted on create: endDatehoursnumber — Total hours requestednotestring — Optional reason / note for the requeststatusstring — Request status. Defaults to 'pending' on create; approve/deny via PATCH.created_atstringupdated_atstring
404- Not found
GET /api/purple-suite/hris/work-authorizations
List work authorizations (visas / right to work)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
employee | query | string | no | Filter to one employee — an email, or the literal 'me' (resolves to the impersonated/default user). |
status | query | string | no | Filter by status (exact match) |
country | query | string | no | Filter by country (exact match) |
Responses
200- Paginated list
application/jsondataarrayarray of:
WorkAuthorizationAn employee's right-to-work record for a country: visa/permit type, status, expiry, and renewal tracking. Citizens and permanent residents have no expiry. The agent stitches this with Purple Expense trips to answer travel-eligibility questions.idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/work-authorizations
Record a work authorization for an employee
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
WorkAuthorization
idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonWorkAuthorizationAn employee's right-to-work record for a country: visa/permit type, status, expiry, and renewal tracking. Citizens and permanent residents have no expiry. The agent stitches this with Purple Expense trips to answer travel-eligibility questions.idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
400- Validation error
GET /api/purple-suite/hris/work-authorizations/{id}
Get a work authorization by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonWorkAuthorizationAn employee's right-to-work record for a country: visa/permit type, status, expiry, and renewal tracking. Citizens and permanent residents have no expiry. The agent stitches this with Purple Expense trips to answer travel-eligibility questions.idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/work-authorizations/{id}
Delete a work authorization
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
PATCH /api/purple-suite/hris/work-authorizations/{id}
Edit a work authorization
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
WorkAuthorization
idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonWorkAuthorizationAn employee's right-to-work record for a country: visa/permit type, status, expiry, and renewal tracking. Citizens and permanent residents have no expiry. The agent stitches this with Purple Expense trips to answer travel-eligibility questions.idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
404- Not found
POST /api/purple-suite/hris/work-authorizations/{id}/renew
File a renewal / extension for a work authorization
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
extend_monthsinteger — Months to extend expiry_date by (default 24).notesstring
Responses
200- Renewal filed
application/jsonWorkAuthorizationAn employee's right-to-work record for a country: visa/permit type, status, expiry, and renewal tracking. Citizens and permanent residents have no expiry. The agent stitches this with Purple Expense trips to answer travel-eligibility questions.idstringemployee_emailstring — The employee this authorization belongs to (matches an Employee.email and the canonical Identity directory).countrystring — Country this authorization grants the right to work in.authorization_typestringstatusstringissued_datestringexpiry_datestring — Null for citizen / permanent_resident.sponsoring_entitystring — Employer/entity sponsoring the visa, if any.renewal_statusstringrenewal_due_datestringtravel_restrictionsarray — Advisories that affect international travel (e.g. advance_parole_required).Advisories that affect international travel (e.g. advance_parole_required).array of:
string
notesstringcreatedAtstringupdatedAtstring
404- Authorization not found
422- Authorization cannot be renewed (no expiry, or already filed)
GET /api/purple-suite/hris/job-families
List job families (career groupings)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
JobFamilyCareer family grouping related job profiles (reference catalog).idstringnamestring requireddescriptionstringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/job-families
Create a job family
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
JobFamily
idstringnamestring requireddescriptionstringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonJobFamilyCareer family grouping related job profiles (reference catalog).idstringnamestring requireddescriptionstringcreatedAtstringupdatedAtstring
400- Validation / missing reference
409- Duplicate
GET /api/purple-suite/hris/job-families/{id}
Get a job family by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonJobFamilyCareer family grouping related job profiles (reference catalog).idstringnamestring requireddescriptionstringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/job-families/{id}
Delete a job family
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
409- Blocked — still referenced by dependents
PATCH /api/purple-suite/hris/job-families/{id}
Rename or edit a job family
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
JobFamily
idstringnamestring requireddescriptionstringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonJobFamilyCareer family grouping related job profiles (reference catalog).idstringnamestring requireddescriptionstringcreatedAtstringupdatedAtstring
400- Validation / missing reference
404- Not found
GET /api/purple-suite/hris/job-levels
List job levels (leveling framework grades)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
JobLevelJob level / grade in the leveling framework (reference catalog).idstring — Level code (IC1–IC6 / M1–M5).namestring requiredtrackstring — Individual-contributor or management track.tierinteger — Numeric rank within the track.management_levelstringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/job-levels
Create a job level
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
JobLevel
idstring — Level code (IC1–IC6 / M1–M5).namestring requiredtrackstring — Individual-contributor or management track.tierinteger — Numeric rank within the track.management_levelstringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonJobLevelJob level / grade in the leveling framework (reference catalog).idstring — Level code (IC1–IC6 / M1–M5).namestring requiredtrackstring — Individual-contributor or management track.tierinteger — Numeric rank within the track.management_levelstringcreatedAtstringupdatedAtstring
400- Validation / missing reference
409- Duplicate
GET /api/purple-suite/hris/job-levels/{id}
Get a job level by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonJobLevelJob level / grade in the leveling framework (reference catalog).idstring — Level code (IC1–IC6 / M1–M5).namestring requiredtrackstring — Individual-contributor or management track.tierinteger — Numeric rank within the track.management_levelstringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/job-levels/{id}
Delete a job level
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
409- Blocked — still referenced by dependents
PATCH /api/purple-suite/hris/job-levels/{id}
Rename or edit a job level
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
JobLevel
idstring — Level code (IC1–IC6 / M1–M5).namestring requiredtrackstring — Individual-contributor or management track.tierinteger — Numeric rank within the track.management_levelstringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonJobLevelJob level / grade in the leveling framework (reference catalog).idstring — Level code (IC1–IC6 / M1–M5).namestring requiredtrackstring — Individual-contributor or management track.tierinteger — Numeric rank within the track.management_levelstringcreatedAtstringupdatedAtstring
400- Validation / missing reference
404- Not found
GET /api/purple-suite/hris/job-profiles
List job profiles (role templates: title + family + level)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
JobProfileJob profile (role template) tying a title to a family + level (reference catalog).idstringtitlestring requiredjob_familystring — JobFamily name.job_levelstring — JobLevel code.management_levelstringcreatedAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/job-profiles
Create a job profile
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
JobProfile
idstringtitlestring requiredjob_familystring — JobFamily name.job_levelstring — JobLevel code.management_levelstringcreatedAtstringupdatedAtstring
Responses
201- Created
application/jsonJobProfileJob profile (role template) tying a title to a family + level (reference catalog).idstringtitlestring requiredjob_familystring — JobFamily name.job_levelstring — JobLevel code.management_levelstringcreatedAtstringupdatedAtstring
400- Validation / missing reference
409- Duplicate
GET /api/purple-suite/hris/job-profiles/{id}
Get a job profile by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonJobProfileJob profile (role template) tying a title to a family + level (reference catalog).idstringtitlestring requiredjob_familystring — JobFamily name.job_levelstring — JobLevel code.management_levelstringcreatedAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/job-profiles/{id}
Delete a job profile
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
409- Blocked — still referenced by dependents
PATCH /api/purple-suite/hris/job-profiles/{id}
Edit a job profile
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
JobProfile
idstringtitlestring requiredjob_familystring — JobFamily name.job_levelstring — JobLevel code.management_levelstringcreatedAtstringupdatedAtstring
Responses
200- Updated
application/jsonJobProfileJob profile (role template) tying a title to a family + level (reference catalog).idstringtitlestring requiredjob_familystring — JobFamily name.job_levelstring — JobLevel code.management_levelstringcreatedAtstringupdatedAtstring
400- Validation / missing reference
404- Not found
GET /api/purple-suite/hris/job-roles
List job roles (positions under a family)
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
limit | query | integer | no | Max items per page (default 50) |
cursor | query | string | no | Pass the previous response's nextCursor to fetch the next page |
$filter | query | string | no | OData filter expression. Comparison operators: eq, ne, gt, ge, lt, le. Logical: and, or, not, with parentheses for grouping. String functions: contains(field,'x'), startswith(field,'x'), endswith(field,'x'). Membership: field in ('a','b'). Case-insensitive matching via tolower(field) / toupper(field). Nested fields use a slash, e.g. pto_balance/vacation_days. String literals use single quotes; dates are ISO-8601. Examples: "status eq 'active'"; "salary gt 50000 and department eq 'Engineering'"; "contains(tolower(name),'acme')"; "closeDate gt 2026-01-01". |
$select | query | string | no | Comma-separated list of fields to return, e.g. "id,firstName,email". Nested fields via slash ("pto_balance/vacation_days"). The id field is always included. |
$orderby | query | string | no | Sort clause(s), comma-separated, each "field [asc|desc]" (asc is the default). Example: "createdAt desc, lastName asc". Null values sort last. |
$search | query | string | no | Free-text, case-insensitive substring match across the resource's searchable fields. |
$top | query | integer | no | Maximum number of items to return (page size). |
$skip | query | integer | no | Number of matching items to skip before returning results (offset paging). Combine with $top. |
$count | query | boolean | no | When true, include @odata.count (total matches after $filter/$search, before paging) in the response. |
Responses
200- Paginated list
application/jsondataarrayarray of:
JobRoleJob role under a family, optionally mapped to a job profile (reference catalog; modeled on sn_hr_core_position).idstringnamestring requireddescriptionstringactivebooleanjob_familystring — JobFamily name.job_profilestring — JobProfile id.createdAtstringupdatedAtstring
nextCursorstring — Cursor for the next page, or null on the last pagetotalinteger — Total documents in the collection
POST /api/purple-suite/hris/job-roles
Create a job role
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes |
Request body
application/json — required
JobRole
idstringnamestring requireddescriptionstringactivebooleanjob_familystring — JobFamily name.job_profilestring — JobProfile id.createdAtstringupdatedAtstring
Responses
201- Created
application/jsonJobRoleJob role under a family, optionally mapped to a job profile (reference catalog; modeled on sn_hr_core_position).idstringnamestring requireddescriptionstringactivebooleanjob_familystring — JobFamily name.job_profilestring — JobProfile id.createdAtstringupdatedAtstring
400- Validation / missing reference
409- Duplicate
GET /api/purple-suite/hris/job-roles/{id}
Get a job role by id
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Found
application/jsonJobRoleJob role under a family, optionally mapped to a job profile (reference catalog; modeled on sn_hr_core_position).idstringnamestring requireddescriptionstringactivebooleanjob_familystring — JobFamily name.job_profilestring — JobProfile id.createdAtstringupdatedAtstring
404- Not found
DELETE /api/purple-suite/hris/job-roles/{id}
Delete a job role
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Responses
200- Deleted
application/jsonsuccessbooleanidstring
404- Not found
409- Blocked — still referenced by dependents
PATCH /api/purple-suite/hris/job-roles/{id}
Edit a job role
Parameters
| Name | In | Type | Required | Description |
|---|---|---|---|---|
X-Instance-ID | header | string | yes | |
id | path | string | yes |
Request body
application/json
JobRole
idstringnamestring requireddescriptionstringactivebooleanjob_familystring — JobFamily name.job_profilestring — JobProfile id.createdAtstringupdatedAtstring
Responses
200- Updated
application/jsonJobRoleJob role under a family, optionally mapped to a job profile (reference catalog; modeled on sn_hr_core_position).idstringnamestring requireddescriptionstringactivebooleanjob_familystring — JobFamily name.job_profilestring — JobProfile id.createdAtstringupdatedAtstring
400- Validation / missing reference
404- Not found