Перейти к основному содержимому

Отслеживание статусов подписания

После отправки документа на подпись нужно отслеживать его прогресс. HRlink не поддерживает webhooks — интегратор сам опрашивает API (стратегия polling).

Что получится в конце

После настройки polling интеграция будет получать изменения статусов документов, определять завершённые и отклонённые документы и сохранять дату последней успешной синхронизации.

Что нужно заранее

Что нужноГде получить
tenantHostАдрес тенантаTenant Экземпляр системы HRlink на отдельном домене (например, company.hr-link.ru). Внутри одного тенанта может быть несколько пространств клиентов. HRlink
clientIdТекущий пользователь
ТокенАутентификация
documentId или externalIdИз ответа на создание документа или из внешней системы
Права на документыАвторизация и права доступа
Поле lastSyncAtХраните на стороне интеграции для инкрементального polling

Какие методы используются

СценарийМетод
Проверить один документПолучить документ
Проверить документ по внешнему IDexternalId Внешний идентификатор сущности — произвольная строка, задаваемая интегратором при создании. Связывает сущность HRlink с записью во внешней системе (1С, SAP и др.) без хранения маппинга UUID.Получить документ по externalId
Получать изменения пачкамиПолучить реестр документов
Остановить подписаниеПрервать подписание документа
Аннулировать подписанный документАннулировать документ

Способы получения статуса

1. Получить конкретный документ

curl -X GET "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}" \
-H "Accept: application/json" \
-H "User-Api-Token: {token}"

2. Реестр документов кадровика

curl -X POST "https://{tenantHost}/api/v1/clients/{clientId}/documents/hrRegistry" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Api-Token: {token}" \
-d '{
"legalEntityIds": ["{UUID юрлица}"],
"limit": 50,
"offset": 0
}'

Основные фильтры реестра:

ПолеНазначение
legalEntityIdsФильтр по юрлицам
documentTypeIdsФильтр по типам документов
documentStatusesФильтр по статусам документов (DocumentStatus)
documentDateFrom / documentDateToДиапазон дат самих документов (поле date документа)
createdDateFrom / createdDateToДиапазон дат создания документа в HRlink
statusLastModifiedDateFrom / statusLastModifiedDateToДиапазон дат последнего изменения статуса — ключевое поле для инкрементального polling
employeeIdsФильтр по сотрудникам-подписантам
baseDocumentExternalIdsФильтр по externalIdexternalId Внешний идентификатор сущности — произвольная строка, задаваемая интегратором при создании. Связывает сущность HRlink с записью во внешней системе (1С, SAP и др.) без хранения маппинга UUID. черновика (для работы с размножением документов)

Полный список фильтров — в OpenAPI-спецификации.

Статусы документа

Значения enum DocumentStatus:

СтатусОписание
DRAFTЧерновик — ожидает отправки на подписание
IN_PROCESSДокумент в процессе подписания (ожидает действий участников)
AWAITING_MY_SIGNINGДокумент ожидает подписания текущим пользователем
COMPLETEDПодписание завершено на всех этапах маршрута
REJECTEDОтклонён одним из участников
ANNULLEDАннулирован
DELETEDУдалён

Определение статуса по маршруту

Детали прогресса подписания — в поле route документа:

{
"route": {
"stages": [
{
"id": "0d07668b-4e28-40a7-b25f-7a5a2a0a3b4c",
"indexNumber": 0,
"type": "SIGNING",
"completenessCondition": "ALL",
"participants": [
{
"id": "9a35f510-9a7c-4f2f-b5a3-8a8f87170f22",
"type": "EMPLOYEE",
"actionType": "SIGNING",
"signedDate": "2025-01-16T10:30:00Z",
"rejectedDate": null,
"seenDate": "2025-01-16T10:25:00Z"
}
]
},
{
"id": "07b8b2fa-7cf7-4d4a-a01e-fb110044c5ef",
"indexNumber": 1,
"type": "SIGNING",
"participants": [
{
"id": "74c60239-d6f5-42f8-bf56-cfb680600415",
"type": "EMPLOYER",
"actionType": "SIGNING",
"signedDate": null,
"rejectedDate": null,
"seenDate": null
}
]
}
]
}
}

Как читать данные маршрута

Для каждого участника (route.stages[n].participants[m]):

ПолеЗначениеЧто означает
signedDateне nullУчастник подписал
rejectedDateне nullУчастник отклонил
seenDateне nullУчастник просмотрел документ
Все nullУчастник ещё не получил документ или не принял решение

Логика определения текущего состояния

Стратегия polling

Выбор паттерна зависит от задачи. Два сценария:

  • Short polling — ждать конкретный документ после отправки (минуты)
  • Incremental polling — отслеживать изменения по всему реестру (часы, дни, постоянно)

Short polling: конкретный документ

Сценарий: только что отправили документ и хотите дождаться, пока он перейдёт в COMPLETED или REJECTED. Вызывайте Получить документ или Получить документ по externalId.

ПараметрЗначение
Первый опросЧерез 30-60 секунд после отправки (время на конвертацию в PDF/A)
Стартовый интервал10-15 секунд
Увеличение интервалаЭкспоненциальное (×1.5), с jitter ±20%
Максимальный интервал5 минут
Общий таймаутЗависит от бизнес-процесса — обычно срок подписания (deadlineDate) плюс запас. Для автоподписания — минуты; для маршрутов с человеком — часы или дни
При 429Экспоненциальный backoff, согласно Ограничениям

Короткий polling — это подстраховка для случаев, когда нужно немедленно среагировать на финальный статус. Для долгого ожидания решений человека переключайтесь на incremental polling.

Incremental polling: изменения по реестру

Сценарий: у вас тысячи документов и нужно подтягивать изменения статусов в вашу систему. Вызывайте Получить реестр документов с фильтром statusLastModifiedDateFrom.

Алгоритм:

  1. Сохраните lastSyncAt = момент начала предыдущего опроса (по часам вашей системы, UTC).
  2. Перед опросом запомните currentSyncAt = now().
  3. Вызовите реестр с statusLastModifiedDateFrom = lastSyncAt - ε, где ε — небольшой буфер (например, 30 секунд) против рассинхрона часов и событий на границе.
  4. При необходимости пройдите по страницам через offset/limit, пока выдача не кончится.
  5. После успешной обработки всей страницы сохраните lastSyncAt = currentSyncAt.
ПараметрЗначение
Интервал между циклами1-5 минут для активных процессов, 15-30 минут для архивных
limit на страницу50 (дефолт) или меньше — для снижения нагрузки на один запрос
Буфер ε перекрытия30-60 секунд — защита от граничных событий между запросами
ФильтрыВсегда задавайте legalEntityIds и по возможности documentStatuses, чтобы сузить выборку
При 429Пропустите цикл, увеличьте интервал до следующего — согласно Ограничениям

Не удаляйте буфер ε — без него при рассогласовании часов серверов можно пропустить изменение, произошедшее в момент запроса.

Большие реестры

При реестрах больше 45 000 документов разбивайте запросы по юрлицам и временным окнам. Без фильтров сервер отвечает медленнее — растёт риск таймаутов и перегрузки интеграции.

Пример incremental polling

Запрос документов, у которых статус изменился с момента последнего опроса.

curl -X POST "https://{tenantHost}/api/v1/clients/{clientId}/documents/hrRegistry" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Api-Token: {token}" \
-d '{
"legalEntityIds": ["{UUID юрлица}"],
"statusLastModifiedDateFrom": "2025-01-15T12:00:00Z",
"documentStatuses": ["COMPLETED", "REJECTED", "ANNULLED"],
"limit": 50,
"offset": 0
}'

Аннулирование документа

Если документ нужно отозвать после отправки на подпись:

curl -X POST "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}/annul" \
-H "Accept: application/json" \
-H "Content-Type: application/json" \
-H "User-Api-Token: {token}" \
-d '{
"reason": "Документ оформлен с ошибкой"
}'

Прерывание подписания

Для прерывания процесса подписания (без аннулирования):

curl -X POST "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}/sign/interrupt" \
-H "Accept: application/json" \
-H "User-Api-Token: {token}"
Разница между аннулированием и прерыванием
  • Аннулирование — документ становится недействительным, нельзя продолжить подписание
  • Прерывание — процесс подписания останавливается, но документ можно отправить заново