Профіль співробітника V2 (Employee Profile V2)¶
Профіль співробітника V2 — це динамічна структура даних на основі блоків та полів. Блоки та поля визначаються конфігурацією профілю компанії (profile definition), що дозволяє кожній компанії налаштовувати структуру анкети під свої потреби.
Кожен блок може містити довільну кількість полів різних типів (текст, число, дата, вибір зі списку, адреса тощо). Блоки ідентифікуються через block_definition_id, а поля — через field_definition_id.
API ендпоінти¶
Усі ендпоінти вимагають заголовок X-Vchasno-Public-Token для автентифікації.
GET /api/public/v2/employee/{employee_id}/profile— отримати профіль співробітника з усіма блоками та значеннями полівPUT /api/public/v2/employee/{employee_id}/profile— повна заміна профілю (REPLACE-семантика: блоки, які не передані в запиті, будуть видалені)PATCH /api/public/v2/employee/{employee_id}/profile— часткове оновлення профілю (MERGE-семантика: оновлюються лише передані блоки, решта залишаються без змін)
Автентифікація¶
Усі запити до V2 профілю потребують заголовок:
X-Vchasno-Public-Token: <ваш_токен>
Токен прив'язаний до конкретної компанії. Операції можливі лише зі співробітниками цієї компанії.
Детальніше про отримання токена: getting_started.md
Рекомендований процес інтеграції¶
- Отримайте конфігурацію профілю — виконайте
GET /api/public/v2/company/employee-profile-definition, щоб дізнатися структуру блоків компанії (block_definition_id,field_definition_id, типи полів, доступні варіанти для полів вибору). Детальніше: Конфігурація профілю співробітника. - Зіставте дані — зіставте вашу модель даних з отриманими блоками та полями, використовуючи
block_definition_idтаfield_definition_id. - Оновіть профіль:
- Використовуйте PUT для повної заміни — всі блоки, що не передані, будуть видалені.
- Використовуйте PATCH для часткового оновлення — передайте лише ті блоки, які потрібно змінити.
Примітка: block_definition_id та field_definition_id стабільні в межах версії профілю компанії. Поле version_identifier у відповіді змінюється при оновленні конфігурації профілю — це можна використовувати для інвалідації кешу.
Структура відповіді (GET)¶
Відповідь завжди обгорнута в об'єкт ResponseModel:
{
"detail": {
"employee": { ... },
"blocks": [ ... ]
}
}
Верхній рівень¶
| Поле | Тип | Опис |
|---|---|---|
employee |
object | Дані співробітника |
blocks |
array | Масив блоків профілю |
Об'єкт співробітника (employee)¶
| Поле | Тип | Опис |
|---|---|---|
id |
UUID | Унікальний ідентифікатор співробітника |
last_name |
string | Прізвище |
first_name |
string | null | Ім'я |
middle_name |
string | null | По-батькові |
ipn |
string | null | ІПН або номер паспорта |
email |
string | null | Особиста електронна пошта |
work_email |
string | null | Робоча електронна пошта |
phone |
string | null | Номер телефону |
position |
string | null | Посада |
date_joined |
date | null | Дата прийому на роботу |
date_of_birth |
date | null | Дата народження |
company_number |
string | null | Табельний номер |
company_id |
UUID | ID компанії |
status |
enum | Статус: candidate, draft, working, fired, archived |
sign_type |
enum | Тип підписання: personal, corporate |
leader_id |
UUID | null | ID адміністративного керівника |
managerial_leader_id |
UUID | null | ID управлінського керівника |
group_id |
UUID | null | ID підрозділу |
external_id |
string | null | Зовнішній ідентифікатор |
user_status |
enum | null | Статус в ЕДО: not_exist, inactive, active, invited, has_app |
invite_sent_at |
datetime | null | Дата відправлення запрошення |
date_created |
datetime | Дата створення |
date_updated |
datetime | Дата останнього оновлення |
employment_type |
enum | Тип зайнятості |
Детальніше про поля співробітника: employee.md
Об'єкт блоку (blocks[])¶
| Поле | Тип | Опис |
|---|---|---|
id |
UUID | null | ID екземпляра блоку (null якщо блок ще не заповнювався) |
block_definition_id |
UUID | ID визначення блоку (використовується в PUT/PATCH запитах) |
version_identifier |
UUID | Версія визначення блоку |
name |
string | Назва блоку (напр. "Особисті дані", "Робоча інформація") |
icon |
string | null | Іконка блоку |
is_repeatable |
boolean | Чи може блок мати декілька екземплярів |
is_archived |
boolean | Чи екземпляр блоку архівований (визначення блоку було видалене з конфігурації компанії, але дані ще зберігаються в профілі) |
order |
integer | Порядок відображення |
source |
string | null | Джерело даних: diia, manual, ai_parsing |
fields |
array | Масив полів блоку |
Об'єкт поля (blocks[].fields[])¶
| Поле | Тип | Опис |
|---|---|---|
field_definition_id |
UUID | ID визначення поля (використовується в PUT/PATCH запитах) |
version_identifier |
UUID | Версія визначення поля |
label |
string | Назва поля |
type |
string | Тип поля (див. розділ "Типи полів") |
placeholder |
string | null | Підказка для заповнення |
options |
array | null | Варіанти для полів вибору (select, radio, multiselect) |
value |
ProfileFieldValue | Поточне значення (тип залежить від type) |
is_archived |
boolean | Чи поле архівоване (визначення поля було видалене з конфігурації компанії, але значення ще зберігається в профілі) |
media_files |
array | Прикріплені файли |
Об'єкт варіанту вибору (options[])¶
| Поле | Тип | Опис |
|---|---|---|
value |
string | Значення варіанту (передається як value при оновленні) |
label |
string | Назва варіанту для відображення |
order |
integer | Порядок відображення |
is_archived |
boolean | true, якщо варіант був видалений із конфігурації компанії, але співробітник все ще має це значення в профілі. У такому випадку UI має відобразити значення як архівне (наприклад, перекреслене) і дозволити переобрати інший варіант. Архівовані варіанти не можна вибрати при новому збереженні. |
Приклад відповіді GET¶
{
"detail": {
"employee": {
"id": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"last_name": "Петренко",
"first_name": "Іван",
"middle_name": "Олександрович",
"ipn": "1234567890",
"email": "[email protected]",
"work_email": "[email protected]",
"phone": "+380501234567",
"position": "Розробник",
"date_joined": "2024-01-15",
"date_of_birth": "1990-05-15",
"company_number": "00123",
"company_id": "11112222-3333-4444-5555-666677778888",
"status": "draft",
"sign_type": "personal",
"leader_id": null,
"managerial_leader_id": null,
"group_id": null,
"external_id": "EXT-001",
"user_status": null,
"invite_sent_at": null,
"date_created": "2024-01-15T10:00:00Z",
"date_updated": "2024-01-15T10:00:00Z",
"employment_type": "main"
},
"blocks": [
{
"id": "b1b2b3b4-b5b6-b7b8-b9b0-b1b2b3b4b5b6",
"block_definition_id": "d1d2d3d4-d5d6-d7d8-d9d0-d1d2d3d4d5d6",
"version_identifier": "v1v2v3v4-v5v6-v7v8-v9v0-v1v2v3v4v5v6",
"name": "Особисті дані",
"icon": "user",
"is_repeatable": false,
"order": 0,
"source": null,
"fields": [
{
"field_definition_id": "f1f2f3f4-f5f6-f7f8-f9f0-f1f2f3f4f5f6",
"version_identifier": "fv1fv2f3-fv4f-v5f6-v7f8-fv9fv0fv1fv2",
"label": "Примітка",
"type": "text",
"placeholder": "Введіть примітку",
"options": null,
"value": "Досвідчений спеціаліст",
"media_files": []
},
{
"field_definition_id": "f2f3f4f5-f6f7-f8f9-f0f1-f2f3f4f5f6f7",
"version_identifier": "fv2fv3f4-fv5f-v6f7-v8f9-fv0fv1fv2fv3",
"label": "Дата початку",
"type": "date",
"placeholder": null,
"options": null,
"value": "2024-01-15",
"media_files": []
},
{
"field_definition_id": "f3f4f5f6-f7f8-f9f0-f1f2-f3f4f5f6f7f8",
"version_identifier": "fv3fv4f5-fv6f-v7f8-v9f0-fv1fv2fv3fv4",
"label": "Відділ",
"type": "select",
"placeholder": null,
"options": [
{"value": "dev", "label": "Розробка", "order": 0},
{"value": "hr", "label": "HR", "order": 1},
{"value": "finance", "label": "Фінанси", "order": 2}
],
"value": "dev",
"media_files": []
}
]
}
]
}
}
Типи полів та формати значень (ProfileFieldValue)¶
Тип поля (type) |
Тип значення | Формат | Приклад |
|---|---|---|---|
text |
string | Довільний текст | "Примітка" |
boolean |
boolean | Логічне значення (так/ні) | true |
number |
integer | float | Числове значення | 42 або 3.14 |
date |
string | ISO 8601: YYYY-MM-DD |
"2024-01-15" |
date_range |
object | Об'єкт з start та end |
{"start": "2024-01-01", "end": "2024-12-31"} |
select |
string | Одне значення з options |
"dev" |
radio |
string | Одне значення з options |
"option_value" |
multiselect |
array | Масив значень з options |
["value1", "value2"] |
checkbox |
array | Масив значень з options |
["value1", "value2"] |
email |
string | Валідний email | "[email protected]" |
phone |
string | Номер телефону | "+380501234567" |
address |
object | Об'єкт адреси (див. нижче) | — |
file |
null | Файли повертаються в media_files; керування ними — через media_file_ids (див. «Вкладення file-полів») |
null |
Щоб очистити значення поля, передайте value: null.
Об'єкт date_range¶
| Поле | Тип | Опис |
|---|---|---|
start |
string | null | Дата початку (YYYY-MM-DD) |
end |
string | null | Дата закінчення (YYYY-MM-DD) |
{"start": "2024-01-01", "end": "2024-12-31"}
Об'єкт address¶
| Поле | Тип | Опис |
|---|---|---|
address |
string | Вулиця |
city |
string | Місто |
region |
string | Область |
country |
string | Країна |
house_number |
string | Номер будинку |
apartment_number |
string | Номер квартири |
{
"address": "вул. Хрещатик",
"city": "Київ",
"region": "Київська",
"country": "Україна",
"house_number": "1",
"apartment_number": "10"
}
Оновлення профілю — PUT (повна заміна)¶
PUT /api/public/v2/employee/{employee_id}/profile
Використовує REPLACE-семантику: профіль буде містити лише ті блоки, які передані в запиті. Блоки, які не передані, будуть видалені. Щоб очистити весь профіль, передайте порожній масив blocks: [].
Операція є ідемпотентною — повторний виклик з тими ж даними дає однаковий результат.
Структура запиту¶
| Поле | Тип | Опис | Обов'язкове |
|---|---|---|---|
blocks |
array | Масив блоків для збереження | Так (може бути порожнім []) |
blocks[].block_definition_id |
UUID | ID визначення блоку | Так |
blocks[].fields |
array | Масив полів блоку | Ні (за замовчуванням []) |
blocks[].fields[].field_definition_id |
UUID | ID визначення поля | Так |
blocks[].fields[].value |
ProfileFieldValue | Нове значення поля | Ні (за замовчуванням null) |
blocks[].fields[].media_file_ids |
array of UUID | ID вкладень, які треба залишити в полі (див. «Вкладення file-полів») | Ні (якщо не передано — вкладення не змінюються) |
Приклад запиту PUT¶
PUT /api/public/v2/employee/a1b2c3d4-e5f6-7890-abcd-ef1234567890/profile
{
"blocks": [
{
"block_definition_id": "d1d2d3d4-d5d6-d7d8-d9d0-d1d2d3d4d5d6",
"fields": [
{
"field_definition_id": "f1f2f3f4-f5f6-f7f8-f9f0-f1f2f3f4f5f6",
"value": "Новий текст примітки"
},
{
"field_definition_id": "f2f3f4f5-f6f7-f8f9-f0f1-f2f3f4f5f6f7",
"value": "2024-06-01"
},
{
"field_definition_id": "f3f4f5f6-f7f8-f9f0-f1f2-f3f4f5f6f7f8",
"value": "hr"
}
]
}
]
}
Приклад: очищення всього профілю¶
PUT /api/public/v2/employee/a1b2c3d4-e5f6-7890-abcd-ef1234567890/profile
{
"blocks": []
}
Відповідь містить оновлений профіль у форматі, ідентичному GET-запиту.
Часткове оновлення профілю — PATCH (злиття)¶
PATCH /api/public/v2/employee/{employee_id}/profile
Використовує MERGE-семантику: оновлюються лише передані блоки, а блоки, які не передані в запиті, залишаються без змін.
Структура запиту¶
| Поле | Тип | Опис | Обов'язкове |
|---|---|---|---|
blocks |
array | Масив блоків для оновлення | Так |
blocks[].block_definition_id |
UUID | ID визначення блоку | Так |
blocks[].fields |
array | Масив полів блоку | Ні (за замовчуванням []) |
blocks[].fields[].field_definition_id |
UUID | ID визначення поля | Так |
blocks[].fields[].value |
ProfileFieldValue | Нове значення поля | Ні (за замовчуванням null) |
blocks[].fields[].media_file_ids |
array of UUID | ID вкладень, які треба залишити в полі (див. «Вкладення file-полів») | Ні (якщо не передано — вкладення не змінюються) |
Приклад запиту PATCH¶
У цьому прикладі оновлюється лише один блок — решта блоків профілю залишаються без змін:
PATCH /api/public/v2/employee/a1b2c3d4-e5f6-7890-abcd-ef1234567890/profile
{
"blocks": [
{
"block_definition_id": "d1d2d3d4-d5d6-d7d8-d9d0-d1d2d3d4d5d6",
"fields": [
{
"field_definition_id": "f1f2f3f4-f5f6-f7f8-f9f0-f1f2f3f4f5f6",
"value": "Оновлений текст"
}
]
}
]
}
Відповідь містить повний оновлений профіль (усі блоки, включаючи ті, що не змінювалися).
Вкладення file-полів¶
Файли полів типу file повертаються в media_files. Завантажити новий файл через Public API неможливо — можна лише зберегти або прибрати вже прикріплені.
media_file_idsне передано — вкладення поля залишаються без змін. Це стосується і полів, які не передані в блоці взагалі: оновлення значень не видаляє файли.media_file_idsпередано — у полі залишаються тільки перелічені файли;[]видаляє всі вкладення поля. Дозволені лишеidзmedia_filesцього ж поля співробітника — будь-який інший ID повертає400 Bad Request.- Для повторюваних блоків (
is_repeatable=true) вкладення зберігаються за порядковим номером екземпляра: N-й переданий екземпляр блока успадковує файли N-го наявного. Якщо змінюєте кількість або порядок екземплярів, передавайтеmedia_file_idsявно. - Блок, не переданий у PUT, видаляється разом зі своїми вкладеннями (REPLACE-семантика). PATCH не змінює непередані блоки, зокрема архівні, та їхні вкладення.
{
"field_definition_id": "f4f5f6f7-f8f9-f0f1-f2f3-f4f5f6f7f8f9",
"value": null,
"media_file_ids": ["0a1b2c3d-4e5f-4a6b-8c7d-9e0f1a2b3c4d"]
}
Правила валідації¶
- Будь-який статус співробітника — оновлення профілю доступне для співробітників у будь-якому статусі (
candidate,draft,working,fired,archived); обмеження за статусом немає. - Валідний
block_definition_id— повинен відповідати існуючому блоку в конфігурації профілю компанії. Невалідний ID повертає400 Bad Request. - Валідний
field_definition_id— повинен відповідати існуючому полю в зазначеному блоці. - Відповідність типів — значення
valueповинно відповідати типу поля (напр. рядок дати для полів типуdate, число дляnumber). - Значення з
options— для полівselect,radio,multiselectзначення повинні бути зі списку доступнихoptionsполя. - Обов'язкові поля — якщо
sign_type=corporate, полеwork_emailє обов'язковим (422 Validation Error). - Вкладення —
media_file_idsможе містити лише ID файлів, уже прикріплених до цього поля співробітника. Інший ID повертає400 Bad Request.
Помилки та їх вирішення¶
| HTTP код | Помилка | Причина | Рішення |
|---|---|---|---|
| 401 | Unauthorized | Відсутній або невалідний X-Vchasno-Public-Token |
Перевірити наявність та коректність токена |
| 403 | Forbidden | Співробітник не належить до компанії токена | Перевірити employee_id — він повинен бути співробітником компанії, до якої прив'язаний токен |
| 404 | Not Found | Співробітник з вказаним employee_id не знайдений |
Перевірити правильність employee_id |
| 400 | Bad Request | Невалідний block_definition_id або field_definition_id, або media_file_ids містить файл, не прикріплений до цього поля |
Отримати актуальні ID через GET-запит профілю |
| 422 | Validation Error | Помилка валідації бізнес-правил (напр. відсутній обов'язковий work_email) |
Перевірити дотримання правил валідації (див. розділ вище) |
Пов'язані сутності¶
- Співробітник (Employee) — поля, статуси, типи підписання
- Автентифікація та початок роботи — отримання токена