Skip to content
Log in Request a demo

Employees

The /api/v1/employees endpoint group covers the full employee synchronization cycle with external HR and payroll systems: creating employee records, updating personal data, maintaining historical tables for employments, positions, and compensations, and archiving terminated employees.

POST /api/v1/employees

Creates a new employee record. Email is not required at creation time.

Required fields:

FieldTypeDescription
first_namestringFirst name
last_namestringLast name
date_effective_fromstring (date)Hire date

Optional fields:

FieldDescription
middle_nameMiddle name
division_idDivision ID
department_idDepartment ID
position_idPosition ID
position_level_idGrade / level ID
location_idLocation ID
legal_entity_idLegal entity ID
reporting_to_idManager ID
employment_contract_idEmployment contract type ID
employment_type_idEmployment type ID
employment_work_pattern_idWork pattern ID
base_salary_grossGross salary
base_salary_netNet salary
currencyCurrency code (ISO 4217)
per_typePeriod: hourly, weekly, monthly, yearly

Request example:

{
"first_name": "John",
"last_name": "Smith",
"date_effective_from": "2024-01-15",
"department_id": 42,
"position_id": 7,
"base_salary_gross": "150000",
"currency": "USD",
"per_type": "monthly"
}

GET /api/v1/employees/{employee_id}

Returns the full employee profile including current position, employment, compensation, and custom fields (custom_fields).


POST /api/v1/employees/search

Returns a page of employees. Filter by text, employee_ids, manager_ids, department_ids, division_ids, location_ids, job_profile_ids, job_role_ids, employment_type_ids, employment_contract_ids, employee_lifecycle_statuses and is_manager. page_size is capped at 500.

Related blocks are not loaded by default - each one must be listed in employee_fields, otherwise its field comes back empty:

ValueFillsContents
position_job_title, position_division, position_department, position_location, position_level, position_reporting_to, position_comment, position_change_reasonemployee_positionCurrent position. Any one of these loads the whole block
employment_employment_type, employment_employment_contract, employment_legal_entity, employment_work_pattern, employment_termination_reasonemployee_employmentCurrent employment
compensation, compensation_change_reasonemployee_compensationCurrent salary: base_salary_gross, base_salary_net, currency, per_type
lifecycle_statuslifecycle_statusLifecycle status
custom_fieldscustom_fieldsCustom fields with values and permissions
time_offtime_offLeave the employee is on today - see below
custom_tablescustom_tablesCustom table rows - see below
additional_compensationsadditional_compensationsPayments of the current month - see below

Request example:

{
"page_number": 1,
"page_size": 100,
"employee_fields": [
"position_job_title",
"position_department",
"compensation",
"custom_fields",
"additional_compensations"
]
}

Filled only when the employee is on leave on the day of the request - the date is not a parameter. For everybody else it is null.

{
"date_from": "2024-03-04",
"date_to": "2024-03-15",
"category": { "id": 3, "title": "Annual leave" },
"balance_requested": "10.00"
}

To find out who is off over a period, use POST /api/v1/time-off/availability/search instead.

One entry per table. A historical table returns its current row only; for the full history read the rows through the table endpoints.

[{
"table_id": 42,
"rows": [{
"id": 5,
"date_effective_from": "2024-01-01",
"is_current": true,
"cells": [{ "field": { "slug": "bonus_amount" }, "value": { "value_float": 5000 } }]
}]
}]

Only the payments whose date_effective_from falls in the current month (UTC). For the whole history use GET /api/v1/employees/{employee_id}/additional-compensations.

[{
"id": 1,
"date_effective_from": "2024-03-01",
"compensation_type": { "id": 7, "title": "Bonus" },
"amount": "500.00",
"amount_gross": "500.00",
"amount_net": null,
"currency": "USD",
"description": "Q1 bonus",
"comment": null
}]

Employees the caller has no employee_additional_compensation view permission for come back with an empty list.


PUT /api/v1/employees/{employee_id}

Updates personal data and custom fields in a single request.

Required fields: first_name, last_name

Optional fields:

FieldDescription
emailWork email
email_personalPersonal email
phoneWork phone
phone_personalPersonal phone
date_birthDate of birth
genderGender
personnel_numberPersonnel number
address_1, address_2, city, state, zipAddress fields
country_idCountry ID
custom_fieldsdict {slug: value} - employee custom field values

Request example:

{
"first_name": "John",
"last_name": "Smith",
"email": "[email protected]",
"personnel_number": "EMP-001",
"custom_fields": {
"tax_id": "123456789"
}
}

DELETE /api/v1/employees/{employee_id}

Soft-deletes the employee (termination). All data is preserved.


A position record captures department, job title, manager, and location at a specific effective date.

POST /api/v1/employees/{employee_id}/positions
FieldTypeDescription
date_effective_fromstring (date)Effective start date
division_idintegerDivision ID
department_idintegerDepartment ID
position_idintegerPosition ID
position_level_idintegerGrade/level ID
reporting_to_idintegerManager ID
legal_entity_idintegerLegal entity ID
location_idintegerLocation ID
commentstringComment
PUT /api/v1/employees/{employee_id}/positions/{id}
DELETE /api/v1/employees/{employee_id}/positions/{id}
POST /api/v1/employees/{employee_id}/positions/search

Returns a paginated list of position records with full nested objects: department, division, position, manager, legal_entity, location.


An employment record captures contract type, employment type, work pattern, and the employment period.

GET /api/v1/employees/{employee_id}/employments

Returns the full list of employment records (current and past).

POST /api/v1/employees/{employee_id}/employments
FieldTypeDescription
date_effective_fromstring (date)Start date (hire date)
date_effective_tostring (date)End date / termination date
employment_type_idintegerEmployment type ID
employment_contract_idintegerContract type ID
work_pattern_idintegerWork pattern ID
date_probation_endsstring (date)Probation end date
commentstringComment
PUT /api/v1/employees/{employee_id}/employments/{id}
DELETE /api/v1/employees/{employee_id}/employments/{id}

A compensation record is a version of the employee’s compensation package effective from date_effective_from until date_effective_to (the day before the next version starts, null for the current one). The package holds the regular amounts: base salary, allowances, deductions, and employer contributions. One-time payments are additional compensations.

POST /api/v1/employees/{employee_id}/compensations
FieldTypeDescription
date_effective_fromstring (date)Effective start date
base_salary_grossnumberGross salary
base_salary_netnumberNet salary
currencystringCurrency (ISO 4217)
per_typestringhourly, weekly, monthly, yearly
change_reason_idintegerChange reason ID
commentstringComment

This method writes the base salary only. Allowances and other package lines are managed in Skailer.

POST /api/v1/employees/{employee_id}/compensations/search

Returns a paginated list of package versions. Each version carries lines - every regular amount of the package:

{
"id": 812,
"date_effective_from": "2026-01-15",
"date_effective_to": null,
"base_salary_gross": "3000.00",
"currency": "USD",
"per_type": "monthly",
"lines": [
{
"id": 1540,
"compensation_type": { "id": 1, "title": "Basic salary", "is_archived": false },
"amount_gross": "3000.00",
"amount_net": null,
"currency": "USD",
"per_type": "monthly",
"description": null,
"kind": "earning",
"is_included_in_gross": true,
"is_payable_to_employee": true,
"is_included_in_total_cost": true,
"rate_type": "fixed_amount",
"percent": null
},
{
"id": 1541,
"compensation_type": { "id": 2, "title": "Housing allowance", "is_archived": false },
"amount_gross": "500.00",
"amount_net": null,
"currency": "USD",
"per_type": "monthly",
"description": null,
"kind": "earning",
"is_included_in_gross": true,
"is_payable_to_employee": true,
"is_included_in_total_cost": true,
"rate_type": "fixed_amount",
"percent": null
}
]
}
Line fieldDescription
compensation_typeCompensation component. The same id comes in compensation_type.id of additional compensations
amount_gross, amount_netAmounts as strings
currency, per_typeCurrency and period of the line
kindearning, deduction, or employer_contribution
is_included_in_grossThe line counts towards gross
is_payable_to_employeeThe line is paid to the employee
is_included_in_total_costThe line counts towards the employer’s total cost
rate_type, percentfixed_amount, or a percent line with its rate; for a percent line the amounts are already calculated

lines is null when the API user has no employee_compensation_lines field permission. Off-payroll payments are not returned.

PUT /api/v1/employees/{employee_id}/compensations/{id}
DELETE /api/v1/employees/{employee_id}/compensations/{id}

Additional compensations are one-time payments: bonuses, premiums, expense reimbursements. Each payment has a single date, date_effective_from, and no end date. Regular allowances are lines of the compensation package.

GET /api/v1/employees/{employee_id}/additional-compensations
POST /api/v1/employees/{employee_id}/additional-compensations
FieldTypeDescription
compensation_type_idintegerCompensation component ID (required)
date_effective_fromstring (date)Payment date (required)
amount_grossnumberGross amount
amount_netnumberNet amount
amountnumberDeprecated: written to amount_gross when amount_gross is not passed
currencystringCurrency code
descriptionstringDescription
commentstringComment
custom_fieldsobjectCustom column values by column slug

The former fields type, frequency_type, and date_effective_to are ignored: every record is saved as a one-time payment.

Update / delete an additional compensation

Section titled “Update / delete an additional compensation”
PUT /api/v1/employees/{employee_id}/additional-compensations/{id}
DELETE /api/v1/employees/{employee_id}/additional-compensations/{id}

Write rows to custom tables linked to an employee (e.g. “Accrued Bonuses”, “Payment Details”). Get the list of available tables and their field slugs via GET /api/v1/custom-fields/tables.

POST /api/v1/employees/{employee_id}/field-tables/{table_id}/rows
FieldTypeDescription
date_effective_fromstring (date)Effective date of this row
cellsobject{slug: value} - cell values

Supported value types in cells:

  • text / textarea / email / phone - string
  • number / currency / percentage - number
  • date - string YYYY-MM-DD
  • datetime - ISO 8601 string
  • select - option ID
  • switch - boolean
  • employee_reference - integer (employee ID)

Request example:

{
"date_effective_from": "2024-01-01",
"cells": {
"bonus_amount": 5000,
"bonus_currency": 1,
"bonus_comment": "Q1 performance bonus"
}
}
PUT /api/v1/employees/{employee_id}/field-tables/{table_id}/rows/{id}
DELETE /api/v1/employees/{employee_id}/field-tables/{table_id}/rows/{id}

Reference lists for the department_id, division_id and team fields of employees and jobs.

GET /api/v1/departments/all

Returns every department, archived included: id, title, emoji, image_url, parent_id, manager (the full employee or null), employees_count and is_archived.

Requires any of: settings_roles_permissions, settings_departments, manage_jobs, manage_leave_policies, manage_approval_policy, see_departments_structure, employee_position_department.

GET /api/v1/divisions/all

Returns every division, archived included: id, title and is_archived.

Requires any of: settings_roles_permissions, settings_divisions, manage_jobs, manage_leave_policies, manage_approval_policy, employee_position_division.

POST /api/v1/teams/search
FieldTypeDescription
textstringSearch by team title
employee_idsarray[integer]Teams that include these employees
page_numberintegerPage number, starts at 1

Returns a paginated list sorted by title. Each team carries id, title, description, emoji, background_url, links (title, url) and members (id, employee, role, sort, description).

Requires any of: manage_teams >= view, settings_roles_permissions, manage_leave_policies, manage_approval_policy.


Full new-hire sync from an HR/payroll system:

  1. Create the employee - POST /api/v1/employees with basic data and hire date.
  2. Update personal data - PUT /api/v1/employees/{id} with email, phone, and custom fields.
  3. Record employment - POST /api/v1/employees/{id}/employments with contract type.
  4. Record compensation - POST /api/v1/employees/{id}/compensations with salary.
  5. Write custom table rows - POST /api/v1/employees/{id}/field-tables/{table_id}/rows for bonuses, payment details, etc.

On termination:

  1. Close the employment record - PUT /api/v1/employees/{id}/employments/{id} (add date_effective_to).
  2. Archive the employee - DELETE /api/v1/employees/{id}.