Home API

API

Serhii
By Serhii
7 articles

How to obtain an access token

An access token is required to authorise subsequent API requests in LMS Smart Way. After obtaining the token, you pass it in the Authorization header with the Bearer type and use it to call the available endpoints in accordance with the scopes embedded in the token. This article shows how to obtain a token, what exactly the API returns in the response, and what to pay attention to before integration. If you are just starting the integration setup, first ensure that you have a valid company_api_key. Prerequisites - You must have a valid company_api_key for your company. - The token request must be sent to the /api/v1/auth/token endpoint. - The API key is passed in the X-API-Key header. - The obtained access token is used only for subsequent API calls and does not replace the API key. Request curl -X POST 'https://smartway.pro/api/v1/auth/token' \ -H 'X-API-Key: <company_api_key>' Successful response { "access_token": "<short_lived_jwt>", "token_type": "Bearer", "expires_in": 900, "scope": "academy.read academy.write employees.read employees.write tests.read tests.write files.read" } Response rules - access_token — short-lived JWT for subsequent public API calls - token_type — always Bearer - expires_in — TTL in seconds - scope — list of scopes separated by spaces embedded in the token What is inside the access token - The JWT contains the companyId claim for tenant isolation. - The JWT also contains the hrEmail claim — the email of the HRADMIN who created or rotated the company’s current active API key. - If another HRADMIN generates or rotates the API key, newly issued tokens will contain a different hrEmail, which will be used for subsequent employee write operations. How to use the access token in subsequent requests After successfully obtaining the token, pass it in the Authorization header in the format Bearer <access_token>. This token is used to authorise subsequent requests to the public API. Before making a request, check that the token has not expired. If it has expired, obtain a new access token by calling the authorisation endpoint again.

Last updated on Mar 28, 2026

How do you get a list of employees via the API?

GET /v1/employees returns a page of employees. If no query parameters are provided, the API applies the defaults: page = 0 and size = 50. Endpoint | Parameter | Value | | -------------- | ---------------------------------------------------- | | Method | GET | | Path | /v1/employees | | Base URL | https://smartway.pro/api | | Auth | Bearer token | | Required scope | employees.read | Purpose This endpoint is used to retrieve a paginated list of employees within the company from the Bearer token. The endpoint supports pagination, full-name search, and filters by department and job title. Prerequisites - The client must send a valid Bearer token. - The token must contain company context. - The token must contain the employees.read scope. - idCompany is not sent by the external client. The BFF takes companyId only from the Bearer token. - Text query parameters support UTF-8 and must be sent as a standard URL-encoded query string. Request Query parameters | Parameter | Type | Required | Description | | ------------- | -------- | ------------ | -------------------------------------------------------------------- | | page | int32 | no | Page number. Default value: 0. | | size | int32 | no | Page size. Default value: 50. | | q | string | no | Partial-match search by full name. Search by email is not supported. | | department | string | no | Department filter. | | jobTitle | string | no | Job title filter. | curl example Call without parameters curl -X GET 'https://smartway.pro/api/v1/employees' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Call with parameters curl -X GET 'https://smartway.pro/api/v1/employees?page=0&size=20&q=Ivan' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Call with multiple UTF-8 parameters curl -G 'https://smartway.pro/api/v1/employees' \ --data-urlencode 'page=0' \ --data-urlencode 'size=20' \ --data-urlencode 'q=Ivan' \ --data-urlencode 'department=Управління' \ --data-urlencode 'jobTitle=Manager' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Response Successful response: 200 OK. Returns EmployeeListResponse. { "data": [ { "employeeId": 4329, "candidateId": 10602, "email": "employee@example.com", "fullName": "Name Surname", "name": "Name", "surname": "Surname", "gender": "Female", "department": "КЛ", "departments": [ "КЛ" ], "jobTitle": "Manager", "jobTitles": [ "Manager" ], "phone": "+380000000000", "active": true } ], "meta": { "page": 0, "size": 50, "totalElements": 385, "totalPages": 8, "hasNext": true } } Response fields EmployeeListResponse | Field | Type | Description | | --------- | ---------- | -------------------------------------- | | data | Employee[] | List of employees on the current page. | | meta | object | Pagination metadata. | Employee | Field | Type | Description | | ----------- | -------- | ------------------------------------------------------ | | employeeId | int64 | Employee ID. | | candidateId | int64 | Linked candidate ID. | | email | string | Employee email. | | fullName | string | Full name generated by the server from name + surname. | | name | string | First name. | | surname | string | Surname. | | gender | string | Gender. | | department | string | Primary department. | | departments | string[] | Set of departments. | | jobTitle | string | Primary job title. | | jobTitles | string[] | Set of job titles. | | phone | string | Phone number. | | active | boolean | Active flag. | Pagination meta | Field | Type | Description | | ------------- | -------- | ------------------------------------------ | | page | int32 | Current page number. Numbering is 0-based. | | size | int32 | Page size. | | totalElements | int64 | Total number of matched elements. | | totalPages | int32 | Total number of pages. | | hasNext | boolean | Indicates whether there is a next page. | Business logic - All query parameters are optional. - If the endpoint is called without parameters, the API returns the first page of employees: page = 0, size = 50. - The page parameter is 0-based: page = 0 is the first page, page = 1 is the second page. - The BFF takes companyId only from the Bearer token. - idCompany is not sent by the external client. - q searches by full name using a partial match. - Search by email is not supported. - q, department, and jobTitle support UTF-8. - Parameters can be combined. The combined set of parameters is applied with AND logic. - Access requires the employees.read scope. Edge cases Edge cases | Scenario | API behaviour | | ------------------------------------------------------------ | --------------------------------------------------------- | | No query parameters are provided | The API applies page = 0 and size = 50. | | page = 0 | The first page is returned. | | page = 1 | The second page is returned. | | q is provided | The API searches by full name using a partial match. | | Email is passed in q | Search by email is not supported. | | department and jobTitle are provided | Filters are combined with AND logic. | | A UTF-8 value is provided, for example department=Управління | The value is valid if sent as a URL-encoded query string. | | Token has no company context | The API returns 403 Forbidden. | Errors Error responses | HTTP status | When it occurs | | ------------------------- | ---------------------------------------------------------- | | 400 Bad Request | Query parameters are invalid. | | 401 Unauthorized | Bearer token is missing or invalid. | | 403 Forbidden | Insufficient permissions or token without company context. | | 500 Internal Server Error | Unexpected BFF error. | | 503 Service Unavailable | Internal integration failure BFF -> back2. | Usage - Run the first integration test without query parameters. - Get the next page with page. - Change the page size with size. - Search for an employee by full name with q. - Filter employees by department or jobTitle. - Combine search and filters to narrow the result set. Common mistakes Typical integration mistakes | Common mistake | Correct approach | | ------------------------------------------ | ---------------------------------------------------------------- | | Assuming page = 1 is the first page | Use page = 0 for the first page. | | Searching for an employee by email using q | q supports full-name search, not email search. | | Sending idCompany in the query string | Do not send idCompany; companyId is taken from the Bearer token. | | Not encoding UTF-8 values in the URL | Send text parameters as a URL-encoded query string. | | Using a token without employees.read | This endpoint requires the employees.read scope. | FAQ Can the endpoint be called without query parameters? Yes. The API applies page = 0 and size = 50. Which page does pagination start from? It starts from page = 0. Is search by email supported? No. The q parameter searches by full name using a partial match. Can filters be combined? Yes. Parameters are combined with AND logic. Do I need to send idCompany? No. The BFF takes companyId from the Bearer token.

Last updated on Apr 25, 2026

How do you get an employee by ID via the API?

GET /v1/employees/{employeeId} returns one employee by ID within the tenant context from the Bearer token. Endpoint | Parameter | Value | | -------------- | ---------------------------------------------------- | | Method | GET | | Path | /v1/employees/{employeeId} | | Base URL | https://smartway.pro/api | | Auth | Bearer token | | Required scope | employees.read | Purpose This endpoint is used to retrieve detailed information about one employee. The lookup is performed only within the tenant context defined by the Bearer token. Prerequisites - The client must send a valid Bearer token. - The token must contain company context. - The token must contain the employees.read scope. - idCompany is not sent separately. - employeeId must belong to an employee within the current tenant. Request Path parameters | Parameter | Type | Required | Description | | ------------- | -------- | ------------ | --------------- | | employeeId | int64 | yes | Employee ID. | curl example Get an employee by ID curl -X GET 'https://smartway.pro/api/v1/employees/3114' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Response Successful response: 200 OK. Returns Employee. { "employeeId": 4329, "candidateId": 10602, "email": "employee@example.com", "fullName": "Name Surname", "name": "Name", "surname": "Surname", "gender": "Female", "department": "КЛ", "departments": [ "КЛ" ], "jobTitle": "Manager", "jobTitles": [ "Manager" ], "phone": "+380000000000", "active": true } Response fields Employee | Field | Type | Description | | ----------- | -------- | ------------------------------------------------------ | | employeeId | int64 | Employee ID. | | candidateId | int64 | Linked candidate ID. | | email | string | Employee email. | | fullName | string | Full name generated by the server from name + surname. | | name | string | First name. | | surname | string | Surname. | | gender | string | Gender. | | department | string | Primary department. | | departments | string[] | Set of departments. | | jobTitle | string | Primary job title. | | jobTitles | string[] | Set of job titles. | | phone | string | Phone number. | | active | boolean | Active flag. | Business logic - The BFF takes companyId from the Bearer token. - idCompany is not sent as a separate parameter. - Employee lookup is performed within the tenant context from the Bearer token. - If employeeId is not found in the current tenant, the API returns 404 Not Found. - Access requires the employees.read scope. - fullName is a derived field and is generated by the server from name + surname. Edge cases Edge cases | Scenario | API behaviour | | --------------------------------------------- | ----------------------------------------------------------------------- | | employeeId exists in the current tenant | The API returns 200 OK and Employee. | | employeeId is not found in the current tenant | The API returns 404 Not Found. | | employeeId exists in another company | The API does not return an employee outside the current tenant context. | | Bearer token has no company context | The API returns 403 Forbidden. | | The client sends idCompany | The endpoint does not use idCompany from the client request. | Errors Error responses | HTTP status | When it occurs | | ------------------------- | ---------------------------------------------------------- | | 400 Bad Request | The request is invalid. | | 401 Unauthorized | Bearer token is missing or invalid. | | 403 Forbidden | Insufficient permissions or token without company context. | | 404 Not Found | Employee was not found within the current tenant. | | 500 Internal Server Error | Unexpected BFF error. | | 503 Service Unavailable | Internal integration failure BFF -> back2. | Usage - Retrieve an employee profile by employeeId. - Check the result of creating or updating an employee. - Synchronise one employee record in an external system. - Check whether employeeId is available within the current tenant. Common mistakes Typical integration mistakes | Common mistake | Correct approach | | ---------------------------------------------------- | ---------------------------------------------------------------------- | | Sending idCompany together with employeeId | Do not send idCompany; the tenant is determined from the Bearer token. | | Using a token without employees.read | Reading an employee requires the employees.read scope. | | Expecting access to an employee from another company | The API looks up only in the current tenant context. | | Treating 404 as a technical error | 404 means the employee was not found in the current tenant. | FAQ Do I need to send idCompany? No. companyId is taken from the Bearer token. Which scope is required? employees.read. What happens if employeeId is not found? The API returns 404 Not Found. Is fullName returned? Yes. fullName is returned as an Employee field and is generated by the server from name + surname.

Last updated on Apr 25, 2026

How do you create an employee via the API?

POST /v1/employees creates an employee. Required body fields: email, name, surname, gender, and active. Access requires the employees.write scope. Endpoint | Parameter | Value | | -------------- | ---------------------------------------------------- | | Method | POST | | Path | /v1/employees | | Base URL | https://smartway.pro/api | | Auth | Bearer token | | Required scope | employees.write | Purpose This endpoint is used to create a new employee within the company from the Bearer token. The active value controls not only the business flag, but also the creation or absence of a linked user in Keycloak. Prerequisites - The client must send a valid Bearer token. - The token must contain company context. - The token must contain the employees.write scope. - idCompany is not sent in the body or query string. - hrEmail is not sent by the external client; the BFF takes it from the Bearer token. - In the current implementation, Idempotency-Key is not used. Request Body parameters | Field | Type | Required | Description | | ----------- | -------- | ------------ | -------------------------------------------------------------------------------------------------------------------------------------------------------------------------- | | email | string | yes | Employee email. | | name | string | yes | Employee first name. This is the source of truth for generating fullName during creation. | | surname | string | yes | Employee surname. This is the source of truth for generating fullName during creation. | | gender | string | yes | Only Male or Female are allowed. | | active | boolean | yes | Only JSON-boolean values true or false are allowed. true creates or synchronises personal account access through Keycloak; false creates the employee without that access. | | department | string | no | Primary department. If not provided, null is stored. | | departments | string[] | no | Set of departments. If not provided, the collection remains empty. | | jobTitle | string | no | Primary job title. If not provided, null is stored. | | jobTitles | string[] | no | Set of job titles. If not provided, the collection remains empty. | | phone | string | no | Phone number. If not provided, null is stored. | | notes | string | no | Notes. If not provided, null is stored. | curl example Create an employee with primary fields and arrays curl -X POST 'https://smartway.pro/api/v1/employees' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data-binary @- <<'JSON' { "email": "employee@example.com", "name": "Ivan", "surname": "Petrenko", "gender": "Female", "active": false, "department": "Management", "departments": ["КЛ"], "jobTitle": "Manager", "jobTitles": ["Coordinator"], "phone": "+380000000000", "notes": "New employee from public API" } JSON Create an employee only with departments/jobTitles arrays curl -X POST 'https://smartway.pro/api/v1/employees' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data-binary @- <<'JSON' { "email": "employee@example.com", "name": "Ivan", "surname": "Petrenko", "gender": "Male", "active": true, "departments": ["Management", "КЛ"], "jobTitles": ["Manager", "Coordinator"], "phone": "+380000000000", "notes": "New employee from public API" } JSON Response Successful response: 201 Created. Returns the created Employee. { "employeeId": 4432, "candidateId": 10748, "email": "employee@example.com", "fullName": "Ivan Petrenko", "name": "Ivan", "surname": "Petrenko", "gender": "Female", "department": "Management", "departments": [ "Management", "КЛ" ], "jobTitle": "Manager", "jobTitles": [ "Coordinator", "Manager" ], "phone": "+380000000000", "active": false } Response fields Employee | Field | Type | Description | | ----------- | -------- | ------------------------------------------------------ | | employeeId | int64 | Employee ID. | | candidateId | int64 | Linked candidate ID. | | email | string | Employee email. | | fullName | string | Full name generated by the server from name + surname. | | name | string | First name. | | surname | string | Surname. | | gender | string | Gender. | | department | string | Primary department. | | departments | string[] | Set of departments. | | jobTitle | string | Primary job title. | | jobTitles | string[] | Set of job titles. | | phone | string | Phone number. | | active | boolean | Active flag. | Business logic - The BFF determines companyId only from the Bearer token. - The BFF takes hrEmail from the Bearer token. hrEmail equals the email of the user with the HRADMIN role who created or rotated the active company API key. - If the active API key is rotated by another HRADMIN, subsequent create operations automatically start using that HRADMIN's hrEmail. - Repeating the same POST does not create a duplicate if an employee with the same email already exists; the API returns 409 Conflict. - gender accepts only Male or Female. - active accepts only JSON-boolean true or false. - active = true creates or synchronises the linked user account in Keycloak and enables access to the personal account. - active = false creates an employee without access to the personal account, that is, without a user in Keycloak. - fullName in the response is generated by the server from name + surname. - If only departments or jobTitles is provided, the first array element becomes the primary value in department or jobTitle. - If both a single field and an array are provided, the single field takes priority as primary, and the array is supplemented with unique values. - If department, jobTitle, phone, or notes is not provided, null is stored in the corresponding single field. - If departments or jobTitles is not provided, the corresponding collection remains empty. - In the response, departments and jobTitles are returned in a stable sorted order. Edge cases Edge cases | Scenario | API behaviour | | ---------------------------------------- | --------------------------------------------------------------------------------------------------- | | A required field is missing | The API returns 400 Bad Request. | | gender is not Male or Female | The API returns 400 Bad Request with an explanation. | | active is sent as a string or number | The API returns 400 Bad Request because active must be JSON-boolean. | | email already exists | The API returns 409 Conflict. | | Only departments is provided | The first array element becomes department. | | department and departments are provided | department remains primary, and departments is supplemented with unique values. | | department or jobTitle is not provided | null is stored in the corresponding single field. | | departments or jobTitles is not provided | The corresponding collection remains empty. | | The client sends fullName | fullName is not described in the create request. The server generates fullName from name + surname. | Errors Error responses | HTTP status | When it occurs | | ------------------------- | ------------------------------------------------------------------------------------ | | 400 Bad Request | At least one required parameter is missing: email, name, surname, gender, or active. | | 400 Bad Request | gender is not Male or Female. | | 400 Bad Request | active is not a JSON-boolean value true or false. | | 401 Unauthorized | Bearer token is missing or invalid. | | 403 Forbidden | Insufficient permissions or token without company context. | | 409 Conflict | An Employee with this email already exists. | | 500 Internal Server Error | Unexpected BFF error. | | 503 Service Unavailable | Internal integration failure BFF -> back2. | Usage - Create an active employee with access to the personal account: active = true. - Create an employee without access to the personal account: active = false. - Send multiple departments or job titles with a defined primary value. - Synchronise employees from an external HR system. Common mistakes Typical integration mistakes | Common mistake | Correct approach | | -------------------------------------------------- | ------------------------------------------------------------------- | | Sending active as the string "true" or "false" | Send true or false as a JSON boolean. | | Sending gender with a value other than Male/Female | Use only Male or Female. | | Sending idCompany or hrEmail | Do not send these values; the BFF takes them from the Bearer token. | | Expecting idempotency through Idempotency-Key | In the current implementation, Idempotency-Key is not used. | | Sending fullName instead of name and surname | Send name and surname; the server generates fullName. | FAQ Which fields are required to create an employee? email, name, surname, gender, and active. What does active = true do? The server creates or synchronises the linked user account in Keycloak and enables access to the personal account. What does active = false do? The employee is created without access to the personal account, that is, without a user in Keycloak. What happens if the email already exists? The API returns 409 Conflict. Do I need to send hrEmail? No. The BFF takes hrEmail from the Bearer token.

Last updated on Apr 25, 2026

How do you partially update an employee via the API?

PATCH /v1/employees/{employeeId} updates only the fields sent in the request. The body must contain at least one field. Access requires the employees.write scope. Endpoint | Parameter | Value | | -------------- | ---------------------------------------------------- | | Method | PATCH | | Path | /v1/employees/{employeeId} | | Base URL | https://smartway.pro/api | | Auth | Bearer token | | Required scope | employees.write | Purpose This endpoint is used to partially update an employee within the current tenant. fullName is not part of the PATCH contract; to change the full name, use name and surname. Prerequisites - The client must send a valid Bearer token. - The token must contain company context. - The token must contain the employees.write scope. - employeeId must belong to an employee within the current tenant. - The PATCH body must contain at least one field. - idCompany and hrEmail are not sent by the external client. Request Path parameters | Parameter | Type | Required | Description | | ------------- | -------- | ------------ | --------------- | | employeeId | int64 | yes | Employee ID. | Body parameters | Field | Type | Required | Description | | ----------- | -------- | ------------ | ------------------------------------------------------------------------------------------- | | email | string | no | Update email. | | name | string | no | Update the employee's first name. If the field is provided, it must contain non-empty text. | | surname | string | no | Update the employee's surname. If the field is provided, it must contain non-empty text. | | gender | string | no | Update gender. | | department | string | no | Update the primary department. | | departments | string[] | no | Replace the full set of departments. | | jobTitle | string | no | Update the primary job title. | | jobTitles | string[] | no | Replace the full set of job titles. | | phone | string | no | Update phone number. | | active | boolean | no | Update the active flag. | curl example Update full name fields, primary fields, arrays, and active curl -X PATCH 'https://smartway.pro/api/v1/employees/4432' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' \ -H 'Content-Type: application/json' \ --data-binary @- <<'JSON' { "name": "Updated Name", "surname": "Surname", "department": "Management", "departments": ["КЛ", "Logistics"], "jobTitle": "Senior Manager", "jobTitles": ["Coordinator", "Analyst"], "active": false } JSON Response Successful response: 200 OK. Returns the updated Employee. { "employeeId": 4432, "candidateId": 10748, "email": "employee@example.com", "fullName": "Updated Name Surname", "name": "Updated Name", "surname": "Surname", "gender": "not_specified", "department": "Management", "departments": [ "Management", "Logistics", "КЛ" ], "jobTitle": "Senior Manager", "jobTitles": [ "Analyst", "Coordinator", "Senior Manager" ], "phone": "+380000000000", "active": false } Response fields Employee | Field | Type | Description | | ----------- | -------- | ------------------------------------------------------ | | employeeId | int64 | Employee ID. | | candidateId | int64 | Linked candidate ID. | | email | string | Employee email. | | fullName | string | Full name generated by the server from name + surname. | | name | string | First name. | | surname | string | Surname. | | gender | string | Gender. | | department | string | Primary department. | | departments | string[] | Set of departments. | | jobTitle | string | Primary job title. | | jobTitles | string[] | Set of job titles. | | phone | string | Phone number. | | active | boolean | Active flag. | Business logic - The BFF takes companyId from the Bearer token, not from request parameters. - The BFF takes hrEmail from the Bearer token. hrEmail equals the email of the user with the HRADMIN role who created or rotated the active company API key. - If the active API key is rotated by another HRADMIN, subsequent patch operations automatically start using that HRADMIN's hrEmail. - PATCH changes only the fields sent in the body. - fullName is not sent in the PATCH body. The server generates fullName from the current name + surname. - name and surname can be sent together or separately. If a field is sent, it must contain non-empty text. - Text fields support UTF-8. - If only departments or jobTitles is provided, the first array element becomes the primary value. - If both a single field and an array are provided, the single field remains primary. - departments and jobTitles arrays in the response are returned in sorted order. - If the new email already belongs to another employee, the API returns 409 Conflict. - If active changes from false to true, the server creates or re-synchronises the linked Keycloak user and enables access to the personal account. - If active changes from true to false, the server deletes the linked Keycloak user and revokes access to the personal account. - If PATCH changes active and email at the same time, the server synchronises the account already linked to this employee, not an arbitrary user by the new email. Edge cases Edge cases | Scenario | API behaviour | | --------------------------------------------- | ------------------------------------------------------------------------ | | PATCH body is empty | The API returns 400 Bad Request. | | name or surname is sent empty | The API returns 400 Bad Request. | | fullName is sent in the PATCH body | The field is not part of the PATCH contract; use name and surname. | | New email already belongs to another employee | The API returns 409 Conflict. | | Only departments or jobTitles is provided | The first array element becomes the primary value. | | A single field and an array are provided | The single field remains primary; the response array is returned sorted. | | active changes from false to true | The server creates or synchronises the linked Keycloak user. | | active changes from true to false | The server deletes the linked Keycloak user. | | active and email are changed at the same time | The account already linked to this employee is synchronised. | Errors Error responses | HTTP status | When it occurs | | ------------------------- | --------------------------------------------------------------------------------------------------------- | | 400 Bad Request | Empty PATCH body or invalid values, including empty name / surname. | | 401 Unauthorized | Bearer token is missing or invalid. | | 403 Forbidden | Insufficient permissions or token without company context. | | 404 Not Found | Employee was not found within the current tenant. | | 409 Conflict | New email is already used by another employee or cannot be safely used to synchronise access in Keycloak. | | 500 Internal Server Error | Unexpected BFF error. | | 503 Service Unavailable | Internal integration failure BFF -> back2. | Usage - Update an employee's contact details. - Change department or job title. - Enable personal account access with active = true. - Revoke personal account access with active = false. - Update email with conflict checking. Common mistakes Typical integration mistakes | Common mistake | Correct approach | | ----------------------------------------------- | ------------------------------------------------------------------- | | Sending an empty PATCH body | Send at least one field to change. | | Sending fullName | Send name and surname. | | Sending empty name or surname | If the field is sent, it must contain non-empty text. | | Expecting active to only change a database flag | active also controls synchronisation of the linked Keycloak user. | | Sending idCompany or hrEmail | Do not send these values; the BFF takes them from the Bearer token. | FAQ Can I send only one field in PATCH? Yes. The body must contain at least one field. Can I change fullName directly? No. fullName is not part of the PATCH contract. Use name and surname. What happens if the new email is already used? The API returns 409 Conflict. What happens when active = false? The server deletes the linked Keycloak user and revokes access to the personal account. What happens if active and email are changed at the same time? The server synchronises the account already linked to this employee.

Last updated on Apr 25, 2026

How do you delete an employee via the API?

DELETE /v1/employees/{employeeId} deletes an employee within the tenant context. A successful response is 204 No Content. Endpoint | Parameter | Value | | -------------- | ---------------------------------------------------- | | Method | DELETE | | Path | /v1/employees/{employeeId} | | Base URL | https://smartway.pro/api | | Auth | Bearer token | | Required scope | employees.write | Purpose This endpoint is used to delete an employee by employeeId. The operation is performed within the tenant context from the Bearer token. Prerequisites - The client must send a valid Bearer token. - The token must contain company context. - The token must contain the employees.write scope. - idCompany is not sent separately. - employeeId must belong to an employee within the current tenant. Request Path parameters | Parameter | Type | Required | Description | | ------------- | -------- | ------------ | --------------- | | employeeId | int64 | yes | Employee ID. | curl example Delete an employee curl -X DELETE 'https://smartway.pro/api/v1/employees/4432' \ -H 'Authorization: Bearer <access_token>' \ -H 'Accept: application/json' Response Successful response: 204 No Content. A successful response has no body. Response fields Delete response | Element | Type | Description | | ------------- | -------------- | ------------------------------------- | | HTTP status | 204 No Content | The operation completed successfully. | | Response body | absent | No body is returned. | Business logic - The BFF takes companyId from the Bearer token, not from request parameters. - The endpoint deletes an employee only within the current tenant context. - Access requires the employees.write scope. Edge cases Edge cases | Scenario | API behaviour | | --------------------------------------------- | ------------------------------------------------------------ | | employeeId is not found in the current tenant | The API returns 404 Not Found. | | Bearer token without employees.write | The API returns 403 Forbidden. | | Operation is successful | The API returns 204 No Content with no body. | | The client sends idCompany | The endpoint does not use idCompany from the client request. | Errors Error responses | HTTP status | When it occurs | | ------------------------- | ---------------------------------------------------------- | | 401 Unauthorized | Bearer token is missing or invalid. | | 403 Forbidden | Insufficient permissions or token without company context. | | 404 Not Found | Employee was not found within the current tenant. | | 500 Internal Server Error | Unexpected BFF error. | | 503 Service Unavailable | Internal integration failure BFF -> back2. | Usage - Delete an employee from LMS Smart Way through an integration. - Clear test records after integration testing. - Remove an employee who should no longer be in the employee dataset. Common mistakes Typical integration mistakes | Common mistake | Correct approach | | ------------------------------------- | ---------------------------------------------------------------- | | Expecting JSON in the response | A successful response is 204 No Content with no body. | | Sending idCompany | Do not send idCompany; companyId is taken from the Bearer token. | | Using a token without employees.write | DELETE requires the employees.write scope. | FAQ What does the API return after successful deletion? 204 No Content with no response body. Do I need to send idCompany? No. companyId is taken from the Bearer token. What happens if employeeId is not found? The API returns 404 Not Found.

Last updated on Apr 25, 2026