Для AI-агентов: markdown этой страницы — /docs-content/workday/records.md индекс документации — /llms.txt
История рабочего дня
GET /v1/workday/records
Возвращает историю рабочих дней сотрудника: время начала и завершения, отработанные секунды и длительность перерывов. Записи отбираются по обязательному идентификатору сотрудника и периоду, а без периода возвращается окно за последние 7 дней.
Параметры
| Параметр | Тип | Обязательный | Описание |
|---|---|---|---|
userId (query) |
number | да | Идентификатор сотрудника, целое больше нуля. Свой идентификатор — GET /v1/users/me, список сотрудников — GET /v1/users |
from (query) |
string | нет | Начало периода, ISO-8601 с явным смещением или Z — например 2026-06-01T00:00:00Z. Отбирает по времени начала дня. Дата без времени возвращает 400. Знак плюса в смещении кодируется как %2B, иначе значение приходит с пробелом вместо знака и не распознаётся |
to (query) |
string | нет | Конец периода в том же формате. Значение from позже to возвращает 400 |
limit (query) |
number | нет | Записей на страницу, от 1 до 50. По умолчанию 50 |
offset (query) |
number | нет | Смещение от начала выборки, целое от нуля. По умолчанию 0. Не сочетается с page |
page (query) |
number | нет | Номер страницы от единицы, равнозначен offset со значением (page − 1) × limit. Не сочетается с offset |
order (query) |
string | нет | Порядок по времени начала дня: desc — от новых к старым, asc — от старых к новым. По умолчанию desc |
Оба конца периода необязательны: если ни from, ни to не переданы, выборка ограничивается последними 7 днями от момента запроса. Параметр запроса вне этого списка возвращает 400 INVALID_PARAMS с именем переданного ключа и перечнем принимаемых.
Примеры
curl — личный ключ
curl -H "X-Api-Key: YOUR_API_KEY" \
"https://vibecode.bitrix24.tech/v1/workday/records?userId=1&from=2020-01-01T00:00:00Z&limit=3&order=asc"
curl — записи другого сотрудника
curl -H "X-Api-Key: YOUR_API_KEY" \
"https://vibecode.bitrix24.tech/v1/workday/records?userId=503&from=2020-01-01T00:00:00Z&limit=3&order=asc"
curl — OAuth-приложение
curl -H "X-Api-Key: YOUR_APP_KEY" \
-H "Authorization: Bearer USER_SESSION_TOKEN" \
"https://vibecode.bitrix24.tech/v1/workday/records?userId=1&from=2020-01-01T00:00:00Z&limit=3&order=asc"
JavaScript — личный ключ
const params = new URLSearchParams({
userId: '1',
from: '2020-01-01T00:00:00Z',
limit: '3',
order: 'asc',
})
const res = await fetch(`https://vibecode.bitrix24.tech/v1/workday/records?${params}`, {
headers: { 'X-Api-Key': 'YOUR_API_KEY' },
})
const { data, meta } = await res.json()
for (const record of data) {
console.log(record.startTime, '— отработано секунд:', record.duration)
}
console.log('Есть ещё записи:', meta.hasMore)
JavaScript — OAuth-приложение
const params = new URLSearchParams({
userId: '1',
from: '2020-01-01T00:00:00Z',
limit: '3',
order: 'asc',
})
const res = await fetch(`https://vibecode.bitrix24.tech/v1/workday/records?${params}`, {
headers: {
'X-Api-Key': 'YOUR_APP_KEY',
'Authorization': 'Bearer USER_SESSION_TOKEN',
},
})
const { data, meta } = await res.json()
Поля ответа
| Поле | Тип | Описание |
|---|---|---|
success |
boolean | true при успешном ответе |
data |
array | Массив записей рабочего дня. Пустой массив, когда под период не попала ни одна запись |
data[].id |
number | Идентификатор записи рабочего дня |
data[].userId |
number | Идентификатор сотрудника, которому принадлежит запись |
data[].startTime |
string | Время начала дня, ISO-8601 со смещением часового пояса сотрудника |
data[].endTime |
string | Время завершения дня в том же формате |
data[].duration |
number | Отработано за день, в секундах |
data[].breakLength |
number | Суммарная длительность перерывов за день, в секундах |
data[].state.status |
string | Состояние записи в нижнем регистре. На проверенных записях приходит closed |
data[].state.recommendedCloseTime |
string | null | Рекомендованное время закрытия дня. На проверенных записях null |
data[].isApproved |
boolean | Признак подтверждённой записи рабочего дня |
meta.hasMore |
boolean | true, когда страница заполнена до limit и за ней есть продолжение |
meta.total |
number | Количество записей в выборке — сумма offset и длины страницы. Приходит только когда страница короче limit |
meta.from |
string | Нижняя граница применённого периода. Приходит, когда она задана — переданным from либо подставленным окном за последние 7 дней |
meta.to |
string | Верхняя граница применённого периода. У периода, открытого сверху (передан только from), поля нет |
Пример ответа
Первые три записи от старых к новым, ?userId=1&from=2020-01-01T00:00:00Z&limit=3&order=asc:
{
"success": true,
"data": [
{
"id": 1,
"userId": 1,
"startTime": "2020-04-23T13:42:10+03:00",
"endTime": "2020-04-23T17:53:26+03:00",
"duration": 12999,
"breakLength": 2077,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 5,
"userId": 1,
"startTime": "2020-04-24T09:16:12+03:00",
"endTime": "2020-04-24T16:30:13+03:00",
"duration": 26041,
"breakLength": 0,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 7,
"userId": 1,
"startTime": "2020-04-27T09:04:11+03:00",
"endTime": "2020-04-27T18:00:00+03:00",
"duration": 32149,
"breakLength": 0,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
}
],
"meta": { "hasMore": true, "from": "2020-01-01T00:00:00Z" }
}
Последняя страница той же выборки, ?userId=1&from=2020-01-01T00:00:00Z&offset=40&order=asc — записей пришло меньше limit, поэтому в meta появляется total:
{
"success": true,
"data": [
{
"id": 163,
"userId": 1,
"startTime": "2024-07-24T17:34:51+03:00",
"endTime": "2024-07-25T02:35:00+03:00",
"duration": 32409,
"breakLength": 0,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 165,
"userId": 1,
"startTime": "2024-08-26T12:34:47+03:00",
"endTime": "2024-08-26T12:58:15+03:00",
"duration": 1408,
"breakLength": 0,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 167,
"userId": 1,
"startTime": "2024-09-05T12:07:30+03:00",
"endTime": "2025-03-27T14:53:08+03:00",
"duration": 17548827,
"breakLength": 311,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 171,
"userId": 1,
"startTime": "2026-05-05T09:52:51+03:00",
"endTime": "2026-05-05T09:53:37+03:00",
"duration": 20,
"breakLength": 26,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 173,
"userId": 1,
"startTime": "2026-05-05T09:55:38+03:00",
"endTime": "2026-05-05T09:55:39+03:00",
"duration": 1,
"breakLength": 0,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
},
{
"id": 175,
"userId": 1,
"startTime": "2026-05-05T10:07:02+03:00",
"endTime": "2026-05-05T10:07:06+03:00",
"duration": 2,
"breakLength": 2,
"state": { "status": "closed", "recommendedCloseTime": null },
"isApproved": true
}
],
"meta": { "hasMore": false, "total": 46, "from": "2020-01-01T00:00:00Z" }
}
Пример ответа при ошибке
400 — не передан обязательный параметр:
{
"success": false,
"error": {
"code": "MISSING_REQUIRED_PARAMS",
"message": "userId is required. Bitrix24 refuses this method without it; get the id from GET /v1/users/me."
}
}
Ошибки
| HTTP | Код | Описание |
|---|---|---|
| 400 | MISSING_REQUIRED_PARAMS |
Не передан userId |
| 400 | INVALID_PARAMS |
Нарушена валидация параметров: некорректный userId, limit вне диапазона от 1 до 50, дата без явного смещения или несуществующая в календаре, from позже to, offset вместе с page, повторённый дважды параметр, смещение больше 999 999 999, неизвестный параметр запроса |
| 401 | MISSING_API_KEY |
Не передан заголовок X-Api-Key |
| 401 | INVALID_API_KEY |
Неверный API-ключ |
| 401 | KEY_EXPIRED |
Срок действия API-ключа истёк |
| 401 | TOKEN_MISSING |
Ключу не настроены OAuth-токены для портала |
| 402 | ACCOUNT_FROZEN |
Баланс портала заморожен |
| 403 | SCOPE_DENIED |
У ключа нет скоупа timeman |
| 403 | BITRIX_ACCESS_DENIED |
Битрикс24 отказал в доступе — в том числе когда у ключа нет права читать табель указанного сотрудника |
| 409 | TIMEMAN_MODULE_NOT_ENABLED |
Битрикс24 не принял метод. Вызовите GET /v1/workday/status: тот же отказ означает, что на портале выключен модуль учёта рабочего времени, ответ 200 — что портал не отдаёт историю рабочего дня, а текущее состояние дня остаётся доступным |
| 422 | BITRIX_ERROR |
Прочие отказы Битрикс24 — текст в message |
| 429 | RATE_LIMITED |
Превышен лимит темпа этого эндпоинта — 30 запросов в минуту на ключ. Для ключа приложения счёт ведётся отдельно по каждому сотруднику |
| 429 | RATE_LIMITED |
Превышен лимит запросов портала Битрикс24 |
| 502 | BITRIX_UNAVAILABLE |
Портал Битрикс24 недоступен |
Полный список общих ошибок API — Ошибки.
Известные особенности
- Ключ не сужает права до личности вызывающего. Личный ключ
vibe_api_…обращается к порталу через входящий вебхук и читает табель правами того сотрудника Битрикс24, под которым этот вебхук выпущен, — то есть правами создателя ключа, а не того, кто ключ применяет. Владелец такого ключа переборомuserIdвыгружает приходы и уходы всей компании. Ключ приложенияvibe_app_…работает иначе — запрос идёт правами сотрудника, открывшего сессию. Кто вправе читать чужой табель, решает Битрикс24, а не платформа: администратор портала или прямой руководитель сотрудника. - Ответ называет применённый период.
meta.fromиmeta.toприходят и тогда, когда период не передавали: иначеmeta.totalсо значением0невозможно отличить от «у сотрудника нет записей вообще», хотя это означает лишь «нет записей за последние 7 дней». У периода, открытого с одной стороны, приходит только заданная граница. - Параметр нельзя передавать дважды.
?userId=1&userId=2возвращает400, а не выбирает одно из значений молча. meta.totalприходит только на короткой странице. На полной странице поля в ответе нет вовсе, поэтому обработчик, читающий его безусловно, получитundefined. Значение верно на момент ответа: приorder=descзапись, добавленная между двумя запросами, сдвигает окно выдачи.- Длительности приходят в секундах.
durationиbreakLength— целые числа секунд. У соседнегоGET /v1/workday/statusдлительности отдаются строкой видаHH:MM:SS, поэтому разбор с одной страницы на другую не переносится. - Отбор ограничен сотрудником и временем начала дня. Других осей у эндпоинта нет: сузить выборку по времени завершения, длительности или признаку подтверждения нельзя, сортировка тоже идёт только по времени начала. Нужный срез собирается из полученных записей на своей стороне.
- Вся история обходится страницами по 50 записей. Больше 50 записей за запрос эндпоинт не отдаёт, глубина берётся через
offsetилиpage. Признак конца выдачи —meta.hasMoreсо значениемfalse. Запрос со смещением за концом выборки возвращает пустой массив, иmeta.totalв таком ответе не приходит.