Lock Days
Lock or unlock individual timesheet days for a user on a Time Clock. Locking a day prevents subsequent edits to that day's time activities until it is unlocked.
Endpoint
| Method | Endpoint | Description |
|---|---|---|
| PUT | /time-clock/v1/time-clocks/{timeClockId}/users/{userId}/lock-days | Lock or unlock specific dates for a user |
Overview
Use this endpoint to programmatically lock or unlock individual days on a user's timesheet:
- Locking a day prevents any edits to that day's punches, shifts, or breaks
- Unlocking a day restores normal edit access
- A single call can change up to 50 dates at once
- The operation is idempotent: dates already in the requested state are silently skipped, and the response always reflects the final state of every date you sent
- This endpoint does not reopen approved payroll periods (see the warning below)
IdempotencyRe-sending the same payload is safe. If a date is already locked when you ask to lock it (or already unlocked when you ask to unlock it), the API returns 200 and the dates are echoed back unchanged — no error, no duplicate work, no extra BI events.
Approved Payroll PeriodsIf
isLockedisfalseand any of the requested dates would actually transition from locked to unlocked but fall inside an approved payroll period for this user, the entire request is rejected with 409 DAYS_IN_APPROVED_PERIOD. No dates are unlocked. Reopen the approved period from the dashboard first, then retry.Locking a day inside an approved period is allowed (it's already effectively locked, so it's a no-op).
Authentication
- API Key (
X-API-KEYheader), or - OAuth 2.0 with scope
time_clock.write
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| timeClockId | integer | Yes | The Time Clock ID the user is assigned to |
| userId | integer | Yes | The user whose days you are locking or unlocking |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| dates | array of strings | Yes | 1–50 unique dates in YYYY-MM-DD format |
| isLocked | boolean | No | true to lock the dates, false to unlock. Defaults to true |
Example Request — Lock
curl --request PUT \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/users/9170357/lock-days \
--header 'X-API-KEY: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"dates": ["2026-04-10", "2026-04-11", "2026-04-12"],
"isLocked": true
}'Example Request — Unlock
curl --request PUT \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/users/9170357/lock-days \
--header 'X-API-KEY: YOUR_API_KEY' \
--header 'Content-Type: application/json' \
--data '{
"dates": ["2026-04-10"],
"isLocked": false
}'Response Structure
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": {
"userId": 9170357,
"isLocked": true,
"dates": ["2026-04-10", "2026-04-11", "2026-04-12"]
}
}Response Fields
| Field | Type | Description |
|---|---|---|
| data.userId | integer | The user from the path, echoed back |
| data.isLocked | boolean | The state applied to all requested dates |
| data.dates | array of strings | The dates from your request, in the order they were sent |
Error Codes
| HTTP Status | Error Code | Description |
|---|---|---|
400 | TIME_CLOCK_NOT_FOUND | The timeClockId does not exist |
400 | USER_NOT_ASSIGNED_TO_TIME_CLOCK | The user is valid but is not assigned to this Time Clock |
400 | Request body validation | Body fails schema validation (empty dates, duplicates, invalid format, > 50 dates, etc.) |
400 | Token missing required scope | OAuth token does not include time_clock.write |
403 | LOCK_DAYS_DISABLED | Timesheet approval / lock days is disabled in this Time Clock's settings |
404 | USER_NOT_FOUND | The userId does not exist in the company |
409 | DAYS_IN_APPROVED_PERIOD | One or more dates to unlock fall inside an approved payroll period |
Integration Example — Lock a Pay Period After Approval
async function lockApprovedPayPeriod(timeClockId, userId, startDate, endDate) {
// Build the date list for the period
const dates = [];
const cursor = new Date(startDate);
const end = new Date(endDate);
while (cursor <= end) {
dates.push(cursor.toISOString().slice(0, 10));
cursor.setDate(cursor.getDate() + 1);
}
// Lock days in chunks of 50 (max per request)
for (let i = 0; i < dates.length; i += 50) {
const chunk = dates.slice(i, i + 50);
const res = await fetch(
`https://api.connecteam.com/time-clock/v1/time-clocks/${timeClockId}/users/$USERID/lock-days`,
{
method: 'PUT',
headers: {
'X-API-KEY': 'YOUR_API_KEY',
'Content-Type': 'application/json'
},
body: JSON.stringify({ dates: chunk, isLocked: true })
}
);
if (!res.ok) {
const err = await res.json();
throw new Error(`Lock failed for ${chunk[0]}..${chunk[chunk.length - 1]}: ${err.error}`);
}
}
}
// Lock January 1-31 for user 9170357 on time clock 12345
await lockApprovedPayPeriod(12345, 9170357, '2026-01-01', '2026-01-31');Notes
Important Considerations
- Locking and unlocking are scoped to a single user on a single Time Clock. Dates locked here do not affect other users or other Time Clocks.
- The endpoint enforces a per-request limit of 50 dates. Loop over chunks of 50 to cover larger ranges.
- Dates can be sent in any order; the response echoes them back in the same order they were sent.
- Locking a day does not retroactively reject existing edits — it only prevents future edits to that day's time activities until it is unlocked.
- The lock-days feature requires Timesheet Approval (Lock Days) to be enabled in the Time Clock settings. If it is disabled, the API returns 403
LOCK_DAYS_DISABLED.
Updated 4 days ago
