Home API How do you create an employee via the API?

How do you create an employee via the API?

Last updated on Apr 25, 2026

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.