Перейти до змісту

Профіль співробітника 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

Рекомендований процес інтеграції

  1. Отримайте конфігурацію профілю — виконайте GET /api/public/v2/company/employee-profile-definition, щоб дізнатися структуру блоків компанії (block_definition_id, field_definition_id, типи полів, доступні варіанти для полів вибору). Детальніше: Конфігурація профілю співробітника.
  2. Зіставте дані — зіставте вашу модель даних з отриманими блоками та полями, використовуючи block_definition_id та field_definition_id.
  3. Оновіть профіль:
  4. Використовуйте PUT для повної заміни — всі блоки, що не передані, будуть видалені.
  5. Використовуйте 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"]
}

Правила валідації

  1. Будь-який статус співробітника — оновлення профілю доступне для співробітників у будь-якому статусі (candidate, draft, working, fired, archived); обмеження за статусом немає.
  2. Валідний block_definition_id — повинен відповідати існуючому блоку в конфігурації профілю компанії. Невалідний ID повертає 400 Bad Request.
  3. Валідний field_definition_id — повинен відповідати існуючому полю в зазначеному блоці.
  4. Відповідність типів — значення value повинно відповідати типу поля (напр. рядок дати для полів типу date, число для number).
  5. Значення з options — для полів select, radio, multiselect значення повинні бути зі списку доступних options поля.
  6. Обов'язкові поля — якщо sign_type=corporate, поле work_email є обов'язковим (422 Validation Error).
  7. Вкладення — 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) Перевірити дотримання правил валідації (див. розділ вище)

Пов'язані сутності