Приход и уход сотрудников
Если в заведении время сотрудников отмечает своя система — мобильное приложение, турникет, СКУД, терминал на входе, — она может отправлять отметки в Mison через API.
Отметки ложатся туда же, куда отметки камеры Hikvision и кассы: их видно на странице «Посещаемость» в кабинете, по ним считается зарплата по часам. Для заведения нет разницы, откуда пришла смена.
Доступ
Раздел открыт только ключу с галочкой «Приход и уход сотрудников». Её включает заведение в кабинете: Интеграции → API-ключи → Редактировать. По умолчанию галочка выключена: отметки влияют на зарплату, поэтому ключ под заказы или отчёты писать их не может.
Без галочки любой метод раздела отвечает 403:
{ "message": "У ключа нет доступа к приходу и уходу сотрудников. Включите его в кабинете: Интеграции → API-ключи" }
Доступ к отчётам для этого раздела не нужен — это отдельная галочка.
Порядок работы
- Загрузите список сотрудников —
GET /attendance/employees— и сопоставьте их со своими. В Mison сотрудник адресуетсяemployee_id. - На каждый приход и уход отправляйте событие —
POST /attendance/events. Можно сразу, можно пачкой из офлайн-очереди. - Для сверки читайте получившиеся смены —
GET /attendance/shifts.
Вам не нужно самим собирать смены: присылайте отдельные события «пришёл» и «ушёл», а Mison сложит их в смены по тем же правилам, что и отметки камеры.
Сотрудники
GET /attendance/employees?point_id={uuid}&search=
Действующие сотрудники бренда — тех, кого можно отмечать. Заблокированные и удалённые сюда не попадают, их отметки не принимаются.
| Параметр | Описание |
|---|---|
point_id | UUID точки, можно несколько через запятую. Без него — все точки ключа |
search | Поиск по имени |
{
"count": 1,
"employees": [
{
"employee_id": 3873,
"name": "Абдулазиз Каримжонов",
"position_id": 1186,
"position_name": "Повар",
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"point_name": "Центральная",
"open_shift": {
"shift_id": 73412,
"check_in": "2026-10-19 08:58:12"
}
}
]
}
open_shift — открытая смена: сотрудник сейчас на смене или забыл отметить уход. null — открытой смены нет. Удобно, чтобы показать в приложении кнопку «Пришёл» или «Ушёл».
point_id сотрудника — точка из его карточки в кабинете. Именно на неё ляжет отметка, если не указать точку в событии.
Отправка отметок
POST /attendance/events
В одном запросе — от 1 до 500 событий. Каждое разбирается отдельно: ошибка в одном не отменяет остальные.
curl -X POST https://backend.mison.uz/api/integrations/v1/attendance/events \
-H "Authorization: Bearer 44595|M4sx2SHynVRIX9CUAS3..." \
-H "Content-Type: application/json" \
-d '{
"events": [
{
"event_id": "door-1-000184",
"employee_id": 3873,
"type": "check_in",
"time": "2026-10-19T08:58:12+05:00"
},
{
"event_id": "door-1-000185",
"employee_id": 3873,
"type": "check_out",
"time": "2026-10-19T18:04:40+05:00",
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388"
}
]
}'
| Поле | Обязательное | Описание |
|---|---|---|
event_id | да | Ваш идентификатор события, до 100 символов. По нему повтор не создаст дубль — см. повторная отправка |
employee_id | да | Сотрудник из GET /attendance/employees |
type | да | check_in — пришёл, check_out — ушёл |
time | да | Когда это произошло на самом деле, а не когда вы отправляете запрос. Формат — ниже |
point_id | нет | UUID точки, где сделана отметка. Без него — точка сотрудника из его карточки |
Формат времени
- ISO 8601 с часовым поясом — рекомендуем:
2026-10-19T08:58:12+05:00или2026-10-19T03:58:12Z. Mison переведёт его в местное время. - Без часового пояса —
2026-10-19 08:58:12или2026-10-19T08:58. Считается местным временем заведения (Ташкент, UTC+5). - Unix-время в секундах —
1792382292(тот же момент, что в примерах выше).
Время не может быть в будущем (часам устройства прощается опережение до 5 минут) и старше 62 дней. Смену за более ранний период заведение вносит в кабинете.
Ответ
Ответ всегда 200, итог — по каждому событию в results, в том же порядке, что в запросе.
{
"accepted": 2,
"duplicates": 0,
"rejected": 0,
"results": [
{
"event_id": "door-1-000184",
"status": "accepted",
"result": "shift_opened",
"shift_id": 73412,
"auto_closed_shift_id": null,
"message": null
},
{
"event_id": "door-1-000185",
"status": "accepted",
"result": "shift_closed",
"shift_id": 73412,
"auto_closed_shift_id": null,
"message": null
}
]
}
400 приходит, только если сломан сам запрос: нет массива events или в нём больше 500 событий.
status — что стало с событием:
status | Что значит | Что делать |
|---|---|---|
accepted | Событие принято. Что именно оно сделало — в result | Удалить из своей очереди |
duplicate | Это event_id уже присылали. result и shift_id — от первой отправки, ничего не изменилось | Удалить из своей очереди |
rejected | Событие не принято, причина — в message | Исправить данные. Повтор того же события получит тот же отказ |
result — что событие сделало со сменой:
result | Что произошло |
|---|---|
shift_opened | Открыта новая смена |
shift_closed | Смена закрыта этим уходом |
check_out_without_shift | Уход без прихода: открытой смены не было. Заведена смена с одним временем ухода — заведение увидит её в «Посещаемости» и поправит |
shift_already_open | Приход, когда сотрудник уже на смене. Ничего не изменилось, shift_id — открытая смена |
already_counted | Такая же отметка этого сотрудника в пределах 5 минут уже есть — с камеры, кассы или от вас под другим event_id. Ничего не изменилось |
inside_shift | Отметка попала внутрь уже закрытой смены — запоздавшее событие. Часы этой смены уже посчитаны, ничего не изменилось |
auto_closed_shift_id заполняется, когда приход закрыл висящую смену (см. правила ниже).
shift_id — идентификатор смены, тот же, что в GET /attendance/shifts.
Причины отказа (message при rejected):
message | Причина |
|---|---|
event_id обязателен | Нет event_id или он пустой |
event_id повторяется в запросе | Два события с одним event_id в одном запросе — принято первое |
type: check_in или check_out | Неизвестный тип события |
time: дата и время в формате ISO 8601… | Время не разобрать |
Время события в будущем | Часы устройства спешат больше чем на 5 минут |
Событие старше 62 дней… | Слишком старое событие — смену вносят в кабинете |
Сотрудник не найден | Нет такого employee_id у бренда или сотрудник удалён |
Сотрудник заблокирован | Сотрудник уволен (заблокирован в кабинете) |
Торговая точка не найдена: … | point_id не принадлежит бренду ключа |
У сотрудника не задана точка — передайте point_id | В карточке сотрудника нет точки, а в событии её не передали |
Как отметки складываются в смены
Правила те же, что у кассы с камерой Hikvision, — смена из API и смена с камеры ведут себя одинаково. Отметки разных точек не смешиваются: приход на одной точке не закрывается уходом на другой.
Приход (check_in)
- Нет открытой смены → открывается новая (
shift_opened). - Сотрудник уже на смене, открытой меньше 14 часов назад, → ничего не меняется (
shift_already_open). Повторное прикладывание карты не открывает вторую смену. - Смена открыта больше 14 часов назад → её уход потерялся. Она закрывается временем нового прихода с пометкой «Автозакрытие: выход не был зарегистрирован», и открывается новая (
shift_opened,auto_closed_shift_id— закрытая смена).
Уход (check_out)
- Закрывает смену, начатую до него (
shift_closed). Смену ищем по времени события, а не «последнюю»: запоздавший уход не закроет смену, которая началась уже после него. - Открытой смены до этого времени нет → заводится смена с одним уходом и пометкой «Выход без открытой смены» (
check_out_without_shift). В часы она не идёт, пока заведение не поправит её в кабинете.
Повторы. Та же отметка этого сотрудника в пределах 5 минут не учитывается второй раз (already_counted) — откуда бы ни пришла первая: от вас, с камеры или с кассы. Отметка внутри уже закрытой смены тоже ничего не меняет (inside_shift).
Повторная отправка
Присылайте у каждого события свой постоянный event_id — номер записи в журнале турникета, UUID, сгенерированный в приложении в момент отметки. Повтор с тем же event_id вернёт duplicate и результат первой отправки, а не откроет вторую смену. Поэтому запрос можно безопасно повторять при таймауте, обрыве сети, 429 или 500.
event_id уникален в пределах ключа. Если под уже использованным event_id прийти с другим событием (другой сотрудник, тип или время), оно не применится: вернётся duplicate с пометкой в message.
Офлайн-очередь. Если устройство работает без сети, копите события и отправляйте пачкой, когда связь вернётся. Внутри одного запроса Mison сам применяет события по времени time, а не по порядку в массиве — уход, оказавшийся в очереди раньше прихода, не сломает смену. Между запросами отправляйте события в порядке времени.
Смены
GET /attendance/shifts?date_from=2026-10-01&date_to=2026-10-19&point_id={uuid}
Смены сотрудников за период — все, а не только присланные вами: с камеры, с кассы и внесённые в кабинете. Это тот же ответ, что у отчёта /reports/attendance, но без доступа к остальным отчётам. Период — до 62 дней, point_id можно не передавать или передать несколько через запятую.
{
"date_from": "2026-10-19",
"date_to": "2026-10-19",
"employees": [
{
"employee_id": 3873,
"employee_login": "user3873",
"employee_name": "Абдулазиз Каримжонов",
"position_name": "Повар",
"hours": 9.11,
"open_shifts": 0,
"worked_days": 1
}
],
"shifts": [
{
"shift_id": 73412,
"employee_id": 3873,
"employee_login": "user3873",
"employee_name": "Абдулазиз Каримжонов",
"position_name": "Повар",
"point_id": "c91fdd54-a539-44ab-8a8f-103838d31388",
"point_name": "Центральная",
"date": "2026-10-19",
"check_in": "2026-10-19 08:58:12",
"check_out": "2026-10-19 18:04:40",
"hours": 9.11,
"source": "api",
"note": null
}
]
}
| Поле | Описание |
|---|---|
shift_id | Идентификатор смены — тот же, что в ответе POST /attendance/events |
source | Откуда смена: api — партнёрское API, cashbox — камера или касса, manual — внесена в кабинете |
note | Пометка: автозакрытие, уход без прихода и т. п. |
check_in / check_out | null — отметки нет: сотрудник ещё на смене или отметка потерялась |
Лимит — 60 запросов в минуту, как у отчётов.
Исправления
Через API смену можно только дополнить новыми отметками — поменять время или удалить смену нельзя. Ошибочную смену заведение правит или удаляет в кабинете на странице «Посещаемость», как смену с камеры. Если заморожена зарплата за прошлый месяц, а смена пришла задним числом, начисление пересчитается само.