Skip to content

Employees (v5)

The v5 Employees API is a modernized replacement for the v4 Users API. It provides cleaner semantics, true PATCH support, dedicated operation endpoints, and richer data includes (tags, employment history, work time arrangements).

Use v5 for new integrations. The v4 Users API remains available but will not receive new features.

Base URL: api/v5/integration/employees · Scope: ditioapiv3

Every endpoint requires an API client with the Administrator role. An employee is looked up by employeeNumber within the company your token belongs to; employees of project companies can’t be managed through this API (403).

Examples use the environment variables from Environments and default to the test environment.

Featurev4 Users APIv5 Employees API
IdentifieridentityId / companyProfileIdemployeeNumber (consistent across all endpoints)
PATCHMerge on companyProfileId; an explicit null is ignoredMerge on employeeNumber; an explicit null clears the value (except birthDate and phone)
EmploymentMixed into user create/updateSeparate dedicated endpoints (create-employment, update-employment, end-employment)
TagsAttach or detach by name; write-only, never returnedFull tag management with date ranges, payroll tags, and diff-based updates; readable via ?include=tags
IncludesFixed response shapeOpt-in via ?include=tags,employment-history,work-time-arrangements
LookupBy profile ID or employee number; no free-text searchBy employee number, plus free-text search across name, phone, email and employee number
SubsidiariesThe list includes subsidiaries for a main-company token; filter with companyIdYour own company by default; opt in with includeEmployeesFromSubsidiaries
POST /api/v5/integration/employees

Creates a new employee profile with an initial employment. The profile and first employment are created together — you cannot create a profile without an employment.

Terminal window
curl -X POST "$DITIO_API_BASE/api/v5/integration/employees" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"employeeNumber": "1042",
"firstName": "Kari",
"lastName": "Nordmann",
"phone": "+4798765432",
"birthDate": "1990-05-15",
"email": "[email protected]",
"workTitle": "Maskinfører",
"employment": {
"startDate": "2026-03-01",
"department": "Anlegg",
"payroll": 1
}
}'

Response: 201 Created with the full employee object, including the created employment and its company context.

400 is returned when the employee number is already used in the company; 409 when the phone number belongs to another active employee in your company structure.

FieldTypeDescription
employeeNumberstringMust not already be used in the company
firstNamestringFirst name
lastNamestringLast name
phonestringPhone number (used as login username)
birthDatedatetimeDate of birth
employmentobjectInitial employment (see below)
employment.startDatedatetimeEmployment start date
FieldTypeDescription
emailstringEmail address
addressstringHome address
workTitlestringJob title
carRegistrationNumberstringCompany car registration
closestRelativestringEmergency contact
personalInfostringAdditional personal info

workCardId and workCardExpirationDate are ignored on create. Set them afterwards with PUT.

FieldTypeDefaultDescription
startDatedatetimerequiredEmployment start date
endDatedatetimenullEmployment end date (null = open-ended)
departmentstringnullDepartment name
mainProjectNumberstringnullDefault project number
payrollint0Payroll type: 0 = NotApplicable, 1 = Variable (the same as payroll: true in the v4 Users API)
GET /api/v5/integration/employees/{employeeNumber}
ParameterTypeDefaultDescription
includeEmployeesFromSubsidiariesboolfalseAlso look in subsidiary companies. Only applies when your token belongs to the main company
includestringComma-separated: tags, work-time-arrangements, employment-history

Returns 404 when no employee has that number, and 400 when the number matches employees in more than one company.

Terminal window
curl "$DITIO_API_BASE/api/v5/integration/employees/1042?include=tags,employment-history" \
-H "Authorization: Bearer $TOKEN"

When employment-history is included, the response adds:

{
"employmentHistory": {
"current": {},
"upcoming": [],
"historical": []
}
}
GET /api/v5/integration/employees
ParameterTypeDefaultDescription
includeEmployeesFromSubsidiariesboolfalseInclude employees from subsidiary companies. Only applies when your token belongs to the main company
includestringComma-separated: tags, work-time-arrangements, employment-history
employeeNumberstringFilter by employee number
GET /api/v5/integration/employees/search?query={query}

Case-insensitive substring search across employee name, phone, email, and employee number. Returns at most 50 hits, as a lightweight response with hasActiveEmployment per hit.

ParameterTypeDefaultDescription
querystringText to search for
includeEmployeesFromSubsidiariesboolfalseAlso search subsidiary companies. Only applies when your token belongs to the main company
Terminal window
curl "$DITIO_API_BASE/api/v5/integration/employees/search?query=Kari" \
-H "Authorization: Bearer $TOKEN"
PUT /api/v5/integration/employees/{employeeNumber}

firstName, lastName and birthDate are required. Despite the verb, PUT is not a full replace:

  • firstName, lastName and email are always overwritten, so leaving out email clears it.
  • Every other field keeps its stored value when you omit it or send null. This is also the only way to set workCardId and workCardExpirationDate.
  • A phone that differs from the stored one changes the login number, as Change phone number does.

Employment changes should use the dedicated employment endpoints below.

PATCH /api/v5/integration/employees/{employeeNumber}

True PATCH semantics: only provided fields are updated, omitted fields remain unchanged, and an explicit null clears a value. The exceptions are birthDate and phone, where null is ignored.

Terminal window
curl -X PATCH "$DITIO_API_BASE/api/v5/integration/employees/1042" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "workTitle": "Prosjektleder", "email": null }'

Patchable fields: firstName, lastName, email, phone, birthDate, address, workTitle, carRegistrationNumber, closestRelative, personalInfo.

DELETE /api/v5/integration/employees/{employeeNumber}

Returns 204 No Content, or 400 when the employee can’t be deleted.

GET /api/v5/integration/employees/{employeeNumber}/deletable
{
"isDeletable": false,
"validationErrors": [
"Employee has registered transactions",
"Employee has active check-ins"
]
}

Disabling prevents the employee from logging in. Both endpoints change only the employee’s profile in your token’s company; profiles the same person has in other companies, such as project companies, are left as they are.

Terminal window
curl -X PATCH "$DITIO_API_BASE/api/v5/integration/employees/1042/disable" \
-H "Authorization: Bearer $TOKEN"
curl -X PATCH "$DITIO_API_BASE/api/v5/integration/employees/1042/enable" \
-H "Authorization: Bearer $TOKEN"

Both return the updated employee response.

PATCH /api/v5/integration/employees/{employeeNumber}/end-employment

Sets endDate on the current active employment of the employee’s profile in your token’s company. Employments in other companies are not changed. Returns 404 when there is no active employment.

Terminal window
curl -X PATCH "$DITIO_API_BASE/api/v5/integration/employees/1042/end-employment" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "endDate": "2026-06-30" }'
POST /api/v5/integration/employees/{employeeNumber}/create-employment

Creates a new employment for an existing employee and returns 201 Created. If a current active employment exists, it is ended the day before the new employment starts; the new startDate must then be later than the current employment’s start date, otherwise the call returns 400.

Terminal window
curl -X POST "$DITIO_API_BASE/api/v5/integration/employees/1042/create-employment" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"startDate": "2026-09-01",
"department": "Maskinavdeling",
"mainProjectNumber": "P-2001",
"payroll": 1
}'
PATCH /api/v5/integration/employees/{employeeNumber}/update-employment

Partial update of the current active employment — only provided fields are updated. Returns 404 when there is no active employment.

PATCH /api/v5/integration/employees/{employeeNumber}/change-employee-number
Terminal window
curl -X PATCH "$DITIO_API_BASE/api/v5/integration/employees/1042/change-employee-number" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "newEmployeeNumber": "2042" }'

The new employee number must not already be used in the company (400).

PATCH /api/v5/integration/employees/{employeeNumber}/change-phone-number

This is an identity-level change that affects all company profiles — the phone number is the login username. Returns 409 when the number belongs to another active user.

Terminal window
curl -X PATCH "$DITIO_API_BASE/api/v5/integration/employees/1042/change-phone-number" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{ "newPhoneNumber": "+4791234567" }'

POST /{employeeNumber}/enable-employee-in-project-company and POST /{employeeNumber}/disable-employee-in-project-company appear in the interactive reference but are not implemented: both return 501 Not Implemented. Don’t call them.

PUT /api/v5/integration/employees/{employeeNumber}/tags

Full replacement of the employee’s tag list. The API computes the diff:

  • Tags in the request but not existing → added
  • Tags existing but not in the request → removed
  • Tags with userTagId provided → updated (only dates can change)

Payroll tags (isPayrollTag = true) allow multiple assignments with non-overlapping date ranges. Regular tags allow only one assignment per tag.

Terminal window
curl -X PUT "$DITIO_API_BASE/api/v5/integration/employees/1042/tags" \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '[
{
"tagName": "Safety Course",
"applicableFromDate": "2026-01-01",
"applicableToDate": null
}
]'
FieldTypeDescription
userTagIdstringFor updates: the existing assignment ID. For new tags: omit
tagIdstringThe tag definition ID. For updates: required. For create: optional (use tagName instead)
tagNamestringTag name. For create: use this OR tagId. For updates: ignored
applicableFromDatedatetimeStart date (required for payroll tags)
applicableToDatedatetimeEnd date (null = open-ended)

The response lists added, updated, removed, and currentTags.

Errors use the standard Integration API error body and status codes; see Errors. The endpoint-specific cases are listed with each endpoint above.

import os
import requests
# Paste get_token (/getting-started/authentication/#getting-a-token-in-your-scripts) above this.
API_BASE = os.environ.get("DITIO_API_BASE", "https://core-api.ditio.dev/core")
headers = {"Authorization": f"Bearer {get_token('ditioapiv3')}"}
def upsert_employee(hr_person):
"""Create the employee if missing, otherwise patch changed profile fields."""
number = hr_person["employee_number"]
lookup = requests.get(
f"{API_BASE}/api/v5/integration/employees/{number}", headers=headers
)
if lookup.status_code == 404:
payload = {
"employeeNumber": number,
"firstName": hr_person["first_name"],
"lastName": hr_person["last_name"],
"phone": hr_person["phone"],
"birthDate": hr_person["birth_date"],
"employment": {"startDate": hr_person["start_date"], "payroll": 1},
}
requests.post(
f"{API_BASE}/api/v5/integration/employees",
headers=headers, json=payload,
).raise_for_status()
else:
changes = {"workTitle": hr_person["title"], "email": hr_person["email"]}
requests.patch(
f"{API_BASE}/api/v5/integration/employees/{number}",
headers=headers, json=changes,
).raise_for_status()