Integration API API reference
Sessions
Shifts derived from the events, from a clock-in to the next clock-out, with work, break, personal and business time. Needs sessions:read.
A session is one shift, derived by MASK from the active events: from a clock_in to the next clock_out, and several a day are fine. Sessions are recomputed whenever an event of the shift changes, so a session's id is stable but its content is not; computedAt says when it was last recomputed.
statusisin_progress(open),complete(closed by aclock_out) orincomplete(left open past the institution's maximum shift length and closed by MASK;endedAtis absent and the open stretch counts nothing).workSeconds,breakSeconds,personalSecondsandbusinessSecondsare the sums of the closed stretches of each kind.intervals[]are the stretches:kind,startedAt, andendedAtandsecondsonce closed.anomalyCountcounts the flagged events of the shift.
List sessions#
/integration/sessionsScope: sessions:readShifts by business date (inclusive, at most 92 days), oldest first (businessDate, startedAt, id), with intervals and totals. 403 institution_not_allowed for an institutionId outside the key.
curl -s "$MASK/integration/sessions?from=2026-11-03&to=2026-11-03&employeeId=24" -H "Authorization: Bearer $KEY"
{
"list": [
{
"id": 4438,
"employeeId": 24,
"institutionId": 1,
"businessDate": "2026-11-03",
"startedAt": 1793689200,
"endedAt": 1793719800,
"status": "complete",
"anomalyCount": 0,
"workSeconds": 30600,
"breakSeconds": 0,
"personalSeconds": 0,
"businessSeconds": 0,
"intervals": [{"kind": "work", "startedAt": 1793689200, "endedAt": 1793719800, "seconds": 30600}],
"computedAt": 1793812958
}
],
"count": 1,
"page": 1,
"pageSize": 50,
"totalPages": 1
}
A shift still open (status=in_progress) has no endedAt, "workSeconds": 0, and its interval reads {"kind": "work", "startedAt": 1793811246}.
Parameters
fromquerydaterequiredFirst business date, ISO yyyy-MM-dd, from 2000-01-01 to 2037-12-31
toquerydaterequiredLast business date, ISO yyyy-MM-dd, from 2000-01-01 to 2037-12-31; from..to spans at most 92 days, both included
institutionIdqueryintegerOne of the key's institutions; omitted = all of them
employeeIdqueryintegerOnly this person's shifts; a person the key cannot see gives an empty list
statusquerystringall | in_progress | complete | incomplete
default "all"
pagequeryinteger1-based
default 1
pageSizequeryinteger1-200
default 50
Responses
Fields of Session page
countintegerlistarray of SessionFields of Session
anomalyCountintegerbreakSecondsintegerbusinessDatedateThe business date at the institution (local start time minus its day boundary), ISO date
businessSecondsintegercomputedAtintegerWhen the shift was last recomputed from its events, epoch seconds
employeeIdintegerendedAtintegerAbsent unless a clock_out closed the shift
idintegerinstitutionIdintegerintervalsarray of IntervalFields of Interval
endedAtintegerAbsent while the stretch is open
kindstringwork, break, personal or business
secondsintegerAbsent while the stretch is open
startedAtintegerEpoch seconds, UTC
personalSecondsintegerstartedAtintegerEpoch seconds, UTC
statusstringin_progress, complete or incomplete (left open past the institution's maximum shift length)
workSecondsinteger
pageintegerpageSizeintegertotalPagesinteger
Errors this route can answer
- 400Bad Request
validation_failedidempotency_requiredevent_too_old - 401Unauthorized
invalid_api_keykey_expiredkey_revoked - 403Forbidden
ip_not_allowedscope_missinginstitution_not_allowednot_api_eventadmin_linked_employee - 429Too Many Requests
rate_limited - 500Internal Server Error
internal_error - 503Service Unavailable
unavailable
Each error has the same JSON body; see Errors for what every code means.
Get session#
/integration/sessions/{id}Scope: sessions:readOne shift with its intervals and totals; 404 when unknown or outside the key's institutions.
A session's id stays the same when the shift is recomputed, so you can re-read a shift you stored earlier.
Parameters
idpathintegerrequired
Responses
Fields of Session
anomalyCountintegerbreakSecondsintegerbusinessDatedateThe business date at the institution (local start time minus its day boundary), ISO date
businessSecondsintegercomputedAtintegerWhen the shift was last recomputed from its events, epoch seconds
employeeIdintegerendedAtintegerAbsent unless a clock_out closed the shift
idintegerinstitutionIdintegerintervalsarray of IntervalFields of Interval
endedAtintegerAbsent while the stretch is open
kindstringwork, break, personal or business
secondsintegerAbsent while the stretch is open
startedAtintegerEpoch seconds, UTC
personalSecondsintegerstartedAtintegerEpoch seconds, UTC
statusstringin_progress, complete or incomplete (left open past the institution's maximum shift length)
workSecondsinteger
Errors this route can answer
- 400Bad Request
validation_failedidempotency_requiredevent_too_old - 401Unauthorized
invalid_api_keykey_expiredkey_revoked - 403Forbidden
ip_not_allowedscope_missinginstitution_not_allowednot_api_eventadmin_linked_employee - 404Not Found
not_found - 429Too Many Requests
rate_limited - 500Internal Server Error
internal_error - 503Service Unavailable
unavailable
Each error has the same JSON body; see Errors for what every code means.