Отслеживание статусов подписания
После отправки документа на подпись получайте изменения через webhook. Периодический polling реестра найдёт изменения, которые ваша система пропустила после длительного сбоя обработчика или деактивации подписки.
Что получится в конце
Ваша система будет получать события об отправке, действиях участников и обновлении печатной формыпечатная формаPDF-документ с визуальным оттиском подписей, который система формирует после завершения документооборота. Печатная форма доступна для скачивания и используется для архивного хранения.. Периодическая сверка найдёт документы, изменения которых ваша система не обработала через webhook.
Что нужно заранее
| Что нужно | Где получить |
|---|---|
| Подписка webhook | Подключение и приём событий |
tenantHost | Адрес тенантаTenantЭкземпляр системы HRlink на отдельном домене (например, company.hr-link.ru). Внутри одного тенанта может быть несколько пространств клиентов. HRlink |
clientId | Текущий пользователь |
| Токен | Аутентификация |
documentId или externalId | Из ответа на создание документа или из внешней системы |
| Права на документы | Авторизация и права доступа |
Поле lastSyncAt | Храните в своей системе для инкрементального polling |
Как выбрать способ
| Способ | Для чего использовать |
|---|---|
| Webhook | Получать изменения без постоянного опроса API |
| Short polling | Сразу после запуска автоматической операции без участия человека дождаться её результата |
| Incremental polling | Периодически сверять реестр и восстанавливать пропущенные изменения |
Форматы входящих событий описаны на странице События и поля.
Какие методы используются
| Сценарий | Метод |
|---|---|
| Проверить один документ | Получить документ |
| Проверить документ по внешнему IDexternalIdВнешний идентификатор сущности — произвольная строка, задаваемая интегратором при создании. Связывает сущность HRlink с записью во внешней системе (1С, SAP и др.) без хранения маппинга UUID. | Получить документ по externalId |
| Получать изменения пачками | Получить реестр документов |
| Остановить подписание | Прервать подписание документа |
| Аннулировать подписанный документ | Аннулировать документ |
Способы получения статуса
1. Получить конкретный документ
- curl
- PowerShell
- HTTP
curl -X GET "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}" \
-H "Accept: application/json" \
-H "User-Api-Token: {token}"
Invoke-RestMethod `
-Method GET `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
}
GET /api/v1/clients/{clientId}/documents/{documentId} HTTP/1.1
Host: {tenantHost}
Accept: application/json
User-Api-Token: {token}
2. Реестр документов кадровика
- curl
- PowerShell
- HTTP
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
}'
$body = @{
legalEntityIds = @("{UUID юрлица}")
limit = 50
offset = 0
} | ConvertTo-Json
Invoke-RestMethod `
-Method POST `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/documents/hrRegistry" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
} `
-ContentType "application/json" `
-Body $body
POST /api/v1/clients/{clientId}/documents/hrRegistry HTTP/1.1
Host: {tenantHost}
Accept: application/json
Content-Type: application/json
User-Api-Token: {token}
{
"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
Polling дополняет webhook. Используйте два сценария:
- Short polling — сразу после запуска автоматической операции без участия человека дождаться её результата;
- Incremental polling — периодически сверять изменения по всему реестру.
Short polling: конкретный документ
Используйте short polling сразу после запуска автоматической операции, которая не требует действия человека, например автоподписания. Чтобы дождаться результата, вызывайте Получить документ или Получить документ по externalId.
| Параметр | Значение |
|---|---|
| Первый опрос | Через 30–60 секунд после отправки (время на конвертацию в PDF/A) |
| Стартовый интервал | 10–15 секунд |
| Увеличение интервала | Экспоненциальное (×1.5), с jitter ±20% |
| Максимальный интервал | 5 минут |
| Общий таймаут | Ваша система задаёт конечный таймаут. После его истечения ваша система прекращает short polling и ожидает событие через webhook либо выполняет периодическую сверку реестра |
| При 429 | Экспоненциальный backoff по правилам раздела Ограничения |
Short polling применяйте только к автоматическим операциям, результат которых нужен сразу. Действия человека отслеживайте через webhook и периодическую сверку реестра.
Incremental polling: изменения по реестру
Сценарий: у вас тысячи документов и нужно подтягивать изменения статусов в вашу систему. Вызывайте Получить реестр документов с фильтром statusLastModifiedDateFrom.
Алгоритм:
- Прочитайте из своего хранилища значение
lastSyncAt, записанное после последнего успешно завершённого цикла. Для первого цикла задайте начальную точку синхронизации в UTC. - Перед опросом запомните
currentSyncAt = now(). - Вызовите реестр с
statusLastModifiedDateFrom = lastSyncAt - ε, гдеε— небольшой буфер (например, 30 секунд) против рассинхрона часов и событий на границе. - Запрашивайте страницы через
limit/offset: после каждой страницы увеличивайтеoffsetнаlimit. Остановитесь, когда реестр вернёт меньшеlimitдокументов. - После успешной обработки всех страниц сохраните
lastSyncAt = currentSyncAt.
| Параметр | Значение |
|---|---|
| Интервал между циклами | 1–5 минут для активных процессов, 15–30 минут для архивных |
limit на страницу | 50 (по умолчанию) или меньше — для снижения нагрузки на один запрос |
Буфер ε перекрытия | 30–60 секунд — защита от граничных событий между запросами |
| Фильтры | Всегда задавайте legalEntityIds. Добавьте documentStatuses, если ваша система отслеживает не все статусы |
| При 429 | Пропустите цикл и увеличьте интервал перед следующим опросом по правилам раздела Ограничения |
Не удаляйте буфер ε — без него при рассинхронизации часов HRlink и вашей системы можно пропустить изменение, произошедшее в момент запроса.
Если реестр содержит больше 45 000 документов, разбивайте запросы по юрлицам и временным окнам. Без фильтров сервер обрабатывает больше документов, что повышает риск таймаутов и перегрузки вашей системы.
Пример incremental polling
Запрос документов, у которых статус изменился с момента последнего опроса.
- curl
- PowerShell
- HTTP
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
}'
$body = @{
legalEntityIds = @("{UUID юрлица}")
statusLastModifiedDateFrom = "2025-01-15T12:00:00Z"
documentStatuses = @("COMPLETED", "REJECTED", "ANNULLED")
limit = 50
offset = 0
} | ConvertTo-Json
Invoke-RestMethod `
-Method POST `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/documents/hrRegistry" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
} `
-ContentType "application/json" `
-Body $body
POST /api/v1/clients/{clientId}/documents/hrRegistry HTTP/1.1
Host: {tenantHost}
Accept: application/json
Content-Type: application/json
User-Api-Token: {token}
{
"legalEntityIds": ["{UUID юрлица}"],
"statusLastModifiedDateFrom": "2025-01-15T12:00:00Z",
"documentStatuses": ["COMPLETED", "REJECTED", "ANNULLED"],
"limit": 50,
"offset": 0
}
Аннулирование документа
Чтобы отозвать документ после отправки на подпись, вызовите Аннулировать документ:
- curl
- PowerShell
- HTTP
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": "Документ оформлен с ошибкой"
}'
$body = @{
reason = "Документ оформлен с ошибкой"
} | ConvertTo-Json
Invoke-RestMethod `
-Method POST `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}/annul" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
} `
-ContentType "application/json" `
-Body $body
POST /api/v1/clients/{clientId}/documents/{documentId}/annul HTTP/1.1
Host: {tenantHost}
Accept: application/json
Content-Type: application/json
User-Api-Token: {token}
{
"reason": "Документ оформлен с ошибкой"
}
Прерывание подписания
Чтобы прервать процесс подписания без аннулирования, вызовите Прервать подписание документа:
- curl
- PowerShell
- HTTP
curl -X POST "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}/sign/interrupt" \
-H "Accept: application/json" \
-H "User-Api-Token: {token}"
Invoke-RestMethod `
-Method POST `
-Uri "https://{tenantHost}/api/v1/clients/{clientId}/documents/{documentId}/sign/interrupt" `
-Headers @{
"Accept" = "application/json"
"User-Api-Token" = "{token}"
}
POST /api/v1/clients/{clientId}/documents/{documentId}/sign/interrupt HTTP/1.1
Host: {tenantHost}
Accept: application/json
User-Api-Token: {token}
- Аннулирование — документ становится недействительным, нельзя продолжить подписание
- Прерывание — процесс подписания останавливается, но документ можно отправить заново