Синхронизация сотрудников
Гайд описывает, как загрузить и поддерживать организационную структуру (юрлица, отделы, должности, пользователи, сотрудники) во внешней системе (1С, SAP, Битрикс24) и в HRlink одной согласованной моделью.
Что получится в конце
После выполнения сценария HRlink создаст или обновит юрлица, отделы, должности, пользователей и сотрудников. Для повторных запусков интеграция сможет передавать только изменившиеся записи.
Что нужно заранее
| Что нужно | Где получить |
|---|---|
tenantHost | Адрес тенантаTenant Экземпляр системы HRlink на отдельном домене (например, company.hr-link.ru). Внутри одного тенанта может быть несколько пространств клиентов. HRlink |
clientId | Текущий пользователь |
| Токен | Аутентификация |
| Внешние идентификаторыexternalId Внешний идентификатор сущности — произвольная строка, задаваемая интегратором при создании. Связывает сущность HRlink с записью во внешней системе (1С, SAP и др.) без хранения маппинга UUID. | В кадровой системе: 1С, SAP, Битрикс24 или другой мастер-системе |
| Данные оргструктуры | Юрлица, отделы, должности, пользователи и сотрудники |
| Права на bulk sync | Авторизация и права доступа |
Какие методы используются
| Шаг | Метод |
|---|---|
| Создать задачу синхронизации | Создать задачу синхронизации |
| Проверить статус задачи | Статус задачи синхронизации |
| Уволить или восстановить сотрудников | Массовое увольнение и восстановление |
| Сверить результат | Получить сотрудников |
Работа с оргструктурой ведётся через Создать задачу синхронизации и Массовое увольнение и восстановление. Bulk sync покрывает все сценарии: первичную загрузку, инкременты, частичные обновления.
Порядок типов синхронизации
Сущности зависят друг от друга, поэтому задачи bulk sync запускаются строго в указанном порядке:
CLIENT_USERS_V6 создаёт пользователей вместе с сотрудниками. Если юрлица, отделы и должности не загружены заранее, задача завершится ошибками валидации по legalEntityExternalId, departmentExternalId, positionExternalId.
| Шаг | Тип задачи | Что синхронизируется |
|---|---|---|
| 1 | LEGAL_ENTITIES | Юрлица |
| 2 | CLIENT_DEPARTMENTS | Отделы (иерархия через parentExternalId) |
| 3 | EMPLOYEE_POSITIONS | Должности |
| 4 | CLIENT_USERS_V6 | Пользователи клиента и их сотрудники одной задачей |
| 5 | EMPLOYEE_FUNCTIONAL_MANAGERS | Управленческие руководители (опционально) |
Запуск задачи bulk sync
Все типы синхронизации создаются одним методом — Создать задачу синхронизации. Отличаются только поля type и data.
- curl
- PowerShell
- HTTP
curl -X POST "https://{tenantHost}/api/v1/clients/{clientId}/bulkDataSyncTasks" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Api-Token: {token}" \
-d '{
"type": "LEGAL_ENTITIES",
"data": [
{
"externalId": "LE-001",
"name": "ООО Компания",
"shortName": "Компания",
"inn": "7712345678",
"ogrn": "1177746123456",
"kpp": "771201001"
}
]
}'
$body = @'
{
"type": "LEGAL_ENTITIES",
"data": [
{
"externalId": "LE-001",
"name": "ООО Компания",
"shortName": "Компания",
"inn": "7712345678",
"ogrn": "1177746123456",
"kpp": "771201001"
}
]
}
'@
Invoke-RestMethod `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/bulkDataSyncTasks" `
-Method POST `
-ContentType "application/json" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
} `
-Body $body
POST /api/v1/clients/{clientId}/bulkDataSyncTasks HTTP/1.1
Host: {tenantHost}
Accept: application/json
Content-Type: application/json
User-Api-Token: {token}
{
"type": "LEGAL_ENTITIES",
"data": [
{
"externalId": "LE-001",
"name": "ООО Компания",
"shortName": "Компания",
"inn": "7712345678",
"ogrn": "1177746123456",
"kpp": "771201001"
}
]
}
В ответе сервер возвращает bulkDataSyncTask.id. Прогресс и итог проверяйте методом Статус задачи синхронизации.
Сервер не блокирует параллельный запуск двух задач одного type через этот метод, но конкурирующие задачи (особенно для CLIENT_DEPARTMENTS) могут давать неожиданные результаты — последующая задача увидит ещё не применённые изменения предыдущей. Безопаснее дождаться финального статуса (SUCCEEDED / FAILED / PARTIALLY_SUCCEEDED) перед запуском следующей задачи того же типа. Задачи разных типов выполняются параллельно.
Шаг 1. Юрлица — LEGAL_ENTITIES
{
"type": "LEGAL_ENTITIES",
"data": [
{
"externalId": "LE-001",
"name": "ООО Компания",
"shortName": "Компания",
"inn": "7712345678",
"ogrn": "1177746123456",
"kpp": "771201001"
}
]
}
| Поле | Обязательность | Описание |
|---|---|---|
externalId | Да | IDid Внутренний идентификатор сущности в формате UUID, генерируемый HRlink при создании. Неизменяемый, используется во всех внутренних операциях. юрлица во внешней системе |
name | Да | Полное название |
shortName | Нет | Короткое название |
inn | Нет | ИНН (10 или 12 цифр) |
ogrn | Нет | ОГРН |
kpp | Нет | КПП |
Шаг 2. Отделы — CLIENT_DEPARTMENTS
Иерархия задаётся через parentExternalId. Корневой отдел создаётся автоматически при создании клиента; ссылайтесь на него через parentExternalId: null или не указывайте поле для отделов первого уровня.
{
"type": "CLIENT_DEPARTMENTS",
"parameters": {
"syncDepartmentsMode": "CREATE_OR_UPDATE"
},
"data": [
{
"externalId": "DEP-IT",
"name": "IT-отдел",
"legalEntityExternalId": "LE-001",
"parentExternalId": null
},
{
"externalId": "DEP-IT-DEV",
"name": "Разработка",
"legalEntityExternalId": "LE-001",
"parentExternalId": "DEP-IT"
}
]
}
Режимы синхронизации отделов
| Режим | Поведение | Когда использовать |
|---|---|---|
CREATE_OR_UPDATE (по умолчанию, если parameters не задан) | Создаёт отсутствующие отделы и обновляет существующие. Отделы, не указанные в data, не трогает | ПолнаЛНА Локальный нормативный акт — внутренний документ организации, с которым сотрудники знакомятся через HRlink. Управляется через отдельный набор API-методов.я или дельта-синхронизация без удалений |
UPDATE | Только обновляет существующие отделы. Отсутствующие в системе пропускает (статус SKIPPED), не создавая | Частичные правки, когда новые отделы создавать не нужно |
Bulk sync для отделов не удаляет отделы, которых нет в data. Удаление выполняется отдельным методом справочника отделов.
Шаг 3. Должности — EMPLOYEE_POSITIONS
{
"type": "EMPLOYEE_POSITIONS",
"data": [
{ "externalId": "POS-DEV", "name": "Разработчик" },
{ "externalId": "POS-QA", "name": "Инженер по тестированию" }
]
}
Шаг 4. Пользователи и сотрудники — CLIENT_USERS_V6
CLIENT_USERS_V6 загружает пользователя клиента (физлицо, идентифицируется по СНИЛС) и одновременно связанных с ним сотрудников. Один человек может быть сотрудником в нескольких юрлицах — все его записи передаются массивом employees.
{
"type": "CLIENT_USERS_V6",
"data": [
{
"snils": "12345678901",
"email": "ivanov@company.ru",
"surname": "Иванов",
"name": "Иван",
"patronymic": "Иванович",
"employees": [
{
"externalId": "EMP-001",
"legalEntityExternalId": "LE-001",
"departmentExternalId": "DEP-IT-DEV",
"positionExternalId": "POS-DEV",
"number": "ТН-042",
"isMainWorkplace": true,
"fullTimeEquivalent": "1.0"
}
]
}
]
}
| Поле | Уровень | Обязательность | Описание |
|---|---|---|---|
snils | userUser Физическое лицо в системе HRlink. Один User соответствует одному реальному человеку. С пользователем связаны персональные данные, документы (СНИЛС, паспорт, ИНН) и логины (email, телефон). | Да | СНИЛС, ключ идентификации физлица |
surname, name | userUser Физическое лицо в системе HRlink. Один User соответствует одному реальному человеку. С пользователем связаны персональные данные, документы (СНИЛС, паспорт, ИНН) и логины (email, телефон). | Да | Фамилия и имя |
patronymic | userUser Физическое лицо в системе HRlink. Один User соответствует одному реальному человеку. С пользователем связаны персональные данные, документы (СНИЛС, паспорт, ИНН) и логины (email, телефон). | Нет | Отчество |
email | userUser Физическое лицо в системе HRlink. Один User соответствует одному реальному человеку. С пользователем связаны персональные данные, документы (СНИЛС, паспорт, ИНН) и логины (email, телефон). | Нет | Email пользователя |
employees[].externalId | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Да | IDid Внутренний идентификатор сущности в формате UUID, генерируемый HRlink при создании. Неизменяемый, используется во всех внутренних операциях. сотрудника во внешней системе |
employees[].legalEntityExternalId | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Да | externalId юрлица из шага 1 |
employees[].departmentExternalId | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Нет | externalId отдела из шага 2 |
employees[].positionExternalId | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Нет | externalId должности из шага 3 |
employees[].number | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Нет | Табельный номер |
employees[].isMainWorkplace | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Нет | Признак основного места работы |
employees[].fullTimeEquivalent | employeeEmployee Связь пользователя пространства клиента с юрлицом — пара (clientUserId, legalEntityId). Один пользователь может иметь несколько записей Employee в разных юрлицах или даже в одном. | Нет | Ставка (FTE), строка вида "1.0" |
Если пользователь с таким snils уже есть в HRlink (например, работает у другого клиента), bulk sync привяжет существующего пользователя к вашему клиенту, а не создаст дубль.
Версии CLIENT_USERS
Каждая версия добавляет одно поле к предыдущей; обратная совместимость сохраняется.
| Версия | Добавленное поле |
|---|---|
CLIENT_USERS (v1) | Базовые поля |
CLIENT_USERS_V2 | availableVacationDayCount |
CLIENT_USERS_V3 | number (табельный номер) |
CLIENT_USERS_V4 | isMainWorkplace |
CLIENT_USERS_V5 | calendarType |
CLIENT_USERS_V6 | fullTimeEquivalent (FTE) |
В новых интеграциях используйте CLIENT_USERS_V6 — он включает все поля предыдущих версий.
Шаг 5. Управленческие руководители — EMPLOYEE_FUNCTIONAL_MANAGERS
Управленческий руководитель (functionalManager) задаётся отдельной задачей после загрузки сотрудников.
{
"type": "EMPLOYEE_FUNCTIONAL_MANAGERS",
"data": [
{
"employeeExternalId": "EMP-001",
"functionalManagerExternalId": "EMP-007"
}
]
}
Руководитель отдела (headManager) — атрибут отдела, задаётся в CLIENT_DEPARTMENTS. Управленческий руководитель (functionalManager) — атрибут конкретного сотрудника, задаётся отдельным типом задачи.
Увольнение и восстановление
Жизненный цикл сотрудника после увольнения и при восстановлении обрабатывает Массовое увольнение/восстановление. Метод принимает массив employees: для увольнения передайте dismissedDate, для восстановления — тот же сотрудник без даты увольнения.
- curl
- PowerShell
- HTTP
curl -X PUT "https://{tenantHost}/api/v1/clients/{clientId}/employees/bulkDismissAndRestore" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Api-Token: {token}" \
-d '{
"employees": [
{ "externalId": "EMP-001", "dismissedDate": "2026-04-15", "version": 5 },
{ "externalId": "EMP-002", "version": 3 }
]
}'
$body = @'
{
"employees": [
{ "externalId": "EMP-001", "dismissedDate": "2026-04-15", "version": 5 },
{ "externalId": "EMP-002", "version": 3 }
]
}
'@
Invoke-RestMethod `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/employees/bulkDismissAndRestore" `
-Method PUT `
-ContentType "application/json" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
} `
-Body $body
PUT /api/v1/clients/{clientId}/employees/bulkDismissAndRestore HTTP/1.1
Host: {tenantHost}
Accept: application/json
Content-Type: application/json
User-Api-Token: {token}
{
"employees": [
{ "externalId": "EMP-001", "dismissedDate": "2026-04-15", "version": 5 },
{ "externalId": "EMP-002", "version": 3 }
]
}
Поле version обязательно для каждой записи — это optimistic lock. Получите актуальное значение через employeeGetEmployeeByExternalId перед запросом.
Стратегия дельта-синхронизации
Для регулярной сверки с внешней системой:
- Запросите реестр сотрудников через
employeeGetPaginatedEmployeesс фильтром по дате изменения. - Сравните выборку с данными внешней системы.
- Сформируйте задачу
CLIENT_USERS_V6со всеми изменёнными и новыми пользователями (bulk sync — это upsert поexternalId). - Уволенных передайте в
employeeBulkDismissAndRestore.employeesсdismissedDate. - Восстановленных передайте в
employeeBulkDismissAndRestore.employeesбезdismissedDate.
Ограничения и пакетирование
-
externalIdобязателен у каждого элементаdataдля всех типов и должен быть уникальным в пределах одной задачи. -
Лимит элементов в
dataзадаётся per-type — единого ограничения нет:Тип Лимит элементов EMPLOYEE_FUNCTIONAL_MANAGERS1000 EMPLOYEE_VACATIONS,EMPLOYEE_VACATIONS_V2,EMPLOYEE_VACATIONS_PLANNING,EMPLOYEE_CUSTOM_STRUCTURE_ELEMENTS,CLIENT_USER_VACATIONS500 LEGAL_ENTITIES,CLIENT_DEPARTMENTS,EMPLOYEE_POSITIONS,CLIENT_USERS_*,CALENDARS,CUSTOM_STRUCTURESсервер не проверяет -
Для типов без серверного лимита всё равно бейте выборку на порции по 500 элементов — нагрузка на API ровнее, ошибки изолируются в маленьких пакетах. Подробнее — Массовые операции → Ограничения.
-
Сервер не блокирует параллельный запуск задач одного типа, но это не значит «безопасно». Дожидайтесь финального статуса предыдущей задачи того же
type— особенно дляCLIENT_DEPARTMENTS, где параллельные задачи могут видеть устаревшее состояние справочника. -
Для
CALENDARSиCUSTOM_STRUCTURESпользователю нужны дополнительные права (CALENDAR_CREATE+CALENDAR_YEARS_EDITиCUSTOM_STRUCTURES_CREATE+CUSTOM_STRUCTURES_UPDATEсоответственно) сверх базовогоBULK_DATA_SYNC_TASKS_CREATE.
При работе с реестрами более 45 000 записей используйте фильтры по датам и юрлицам, чтобы разбить выборку на порции. ПолнаЛНА Локальный нормативный акт — внутренний документ организации, с которым сотрудники знакомятся через HRlink. Управляется через отдельный набор API-методов.я выгрузка без фильтров медленнее и сильнее нагружает API.