Manual Break Clocking
Start and end a live manual break for an employee, mirroring the Connecteam mobile app's "take a break" experience. Unlike Create time activities — which writes a completed, historical break — these endpoints open and close a break in the live punch lifecycle, so a physical clock device or kiosk stays in sync with the employee's real state.
The key advantage is the automatic shift transition: if the employee is clocked into a shift when the break starts, the server closes that shift and opens the break in a single call. When the break ends, the server can re-open the shift on the same job automatically — no two-step orchestration, no race conditions on flaky connections.
Endpoints
| Method | Endpoint | Description |
|---|---|---|
| POST | /time-clock/v1/time-clocks/{timeClockId}/manual-breaks/{manualBreakId}/clock-in | Start a manual break (auto-closes an open shift) |
| POST | /time-clock/v1/time-clocks/{timeClockId}/manual-breaks/clock-out | End the open manual break (optionally resume the shift) |
Get the manual break IDs firstThe
manualBreakIdpath parameter is the ID of a manual break type configured on the time clock (e.g. "Lunch", "Rest"). Retrieve the available types — and whether manual breaks are enabled — from Settings & Configuration (GET /time-clock/v1/time-clocks/{timeClockId}/manual-breaks).
How It Works
These endpoints reproduce the mobile app's one-tap break flow. The server inspects the employee's current state and does the right thing automatically.
Starting a break (clock-in)
| State when calling clock-in | Server action | Response |
|---|---|---|
| Idle (not on a shift) | Opens a standalone break | isSwitchFromShift: false |
| On an open shift (same time clock) | Closes the shift and opens the break in one call, attributing the break to the shift's job | isSwitchFromShift: true, closedShift present |
| Already on a manual break | Rejected | 400 ALREADY_ON_BREAK |
| On an open shift on a different time clock | Break starts independently (per-time-clock state) | isSwitchFromShift: false |
Ending a break (clock-out)
| State when calling clock-out | isResumeShift (request) | Server action | Response |
|---|---|---|---|
| Break started from a shift | true (default) | Ends the break and re-opens the source shift on the same job | isResumeShift: true, resumedShift present |
| Break started from a shift | false | Ends the break only — employee becomes idle | isResumeShift: false |
| Standalone break | any | Ends the break only — no shift to resume | isResumeShift: false |
| No open break | any | Rejected | 400 NO_OPEN_BREAK |
The response reflects the actual outcome
isResumeShiftin the response may befalseeven if you requestedtrue— for example, when the break was standalone and there is no shift to resume. Always read the returned value rather than assuming the request value was applied.
Mandatory Breaks (Early-Return Restriction)
A manual break type can be configured as mandatory with a minimum duration. When a break is mandatory, the employee cannot end it early — it must run for its full configured duration. This mirrors the mobile and dashboard behavior, where the "End break" button is disabled until the minimum is reached.
| Elapsed time (break start → end) | Result |
|---|---|
| ≤ 45 seconds | Allowed — short grace window to undo an accidental start |
45s < elapsed < configured duration | Blocked — 400 MANDATORY_BREAK_TOO_SHORT |
≥ configured duration | Allowed |
The restriction applies to every end pathMandatory minimums are enforced even when
isResumeShift: true. An employee cannot use auto-resume to return to their job before a mandatory break completes. For non-mandatory breaks there is no restriction — they can be ended at any time.
When an offline timestamp is supplied on clock-out, the elapsed duration is measured against that timestamp (not the current server time), so a break that legitimately ran its full duration offline is not wrongly blocked.
Offline Mode (Retroactive Punches)
Both endpoints accept an optional timestamp (Unix seconds), identical in behavior to Real-Time Clocking. Use it when a physical clock device flushes queued punches after reconnecting, so the timesheet reflects when the break actually happened.
Timestamp rules (whentimestampis supplied)
- Unix time in seconds
- Not in the future
- No more than 12 hours in the past
- Clock-out only: must be strictly after the open break's start time
- Clock-out only: the punch day must not be locked or approved
- Must not overlap an already-completed shift or break
- When omitted, the server captures the time at request receipt
For breaks older than 12 hours, use Create time activities instead.
Authentication
Both endpoints require authentication via API key or OAuth 2.0.
- API Key —
X-API-KEYheader, or - OAuth 2.0 — scope
time_clock.write
Clock In to a Manual Break
Start a manual break for an employee. If the employee is clocked into a shift on the same time clock, the shift is automatically closed and the break is started in one call (attributed to the shift's job). If the employee is idle, the break starts standalone.
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| timeClockId | integer | Yes | Time clock ID |
| manualBreakId | string | Yes | ID of the manual break type to start (from the manual-breaks settings) |
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| userId | integer | Yes | User's ID (must be assigned to the time clock) |
| timezone | string | No | Tz format (e.g., America/New_York). Defaults to the time clock setting |
| timestamp | integer | No | Break-start time in Unix seconds. Omitted = server-now. Max 12 hours in the past; not in the future. Use when flushing offline punches. |
| locationData | object | No | GPS coordinates and address |
| locationData.latitude | number | No | Latitude coordinate |
| locationData.longitude | number | No | Longitude coordinate |
| locationData.address | string | No | Address associated with the GPS data |
User Assignment & Manual Breaks EnabledThe user must be assigned to the time clock, and manual breaks must be enabled for that time clock. Otherwise the request is rejected with
USER_NOT_ASSIGNEDorMANUAL_BREAKS_DISABLED.
Example: Start a Break While Idle (Standalone)
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/8b8a161e-dfb5-42ac-bbf0-0448fc0c0c82/clock-in \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York"
}'Example: Start a Break From an Open Shift (Auto-Close Shift)
When the employee is on a shift, the same call closes the shift and opens the break:
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/8b8a161e-dfb5-42ac-bbf0-0448fc0c0c82/clock-in \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York"
}'Example: Start a Break With Location
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/8b8a161e-dfb5-42ac-bbf0-0448fc0c0c82/clock-in \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York",
"locationData": {
"address": "123 Main St, New York, NY 10001",
"latitude": 40.7128,
"longitude": -74.0060
}
}'Example: Retroactive Break Start (Offline Mode)
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/8b8a161e-dfb5-42ac-bbf0-0448fc0c0c82/clock-in \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York",
"timestamp": 1748345820
}'The returned data.start.timestamp equals 1748345820.
Response: Break Started While Idle
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": {
"id": "break_activity_xyz789",
"start": {
"timestamp": 1748345820,
"timezone": "America/New_York"
},
"isSwitchFromShift": false
}
}Response: Break Started From an Open Shift
The closedShift object describes the shift that was automatically closed:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": {
"id": "break_activity_xyz789",
"start": {
"timestamp": 1748345820,
"timezone": "America/New_York"
},
"isSwitchFromShift": true,
"closedShift": {
"id": "shift-abc123",
"userId": 9170357,
"start": {
"timestamp": 1748342220,
"timezone": "America/New_York",
"source": { "type": "api" }
},
"end": {
"timestamp": 1748345820,
"timezone": "America/New_York",
"source": { "type": "api" }
},
"jobId": "job-123"
}
}
}Clock-In Response Fields
| Field | Type | Description |
|---|---|---|
| requestId | string | Unique identifier for this API request |
| data.id | string | ID of the break activity that was started |
| data.start.timestamp | integer | Break start time recorded by the server (Unix seconds) |
| data.start.timezone | string | Tz format timezone |
| data.isSwitchFromShift | boolean | true if an open shift was automatically closed to start this break; false if the employee was idle |
| data.closedShift | object | The shift that was closed. Present only when isSwitchFromShift is true |
Clock Out From a Manual Break
End the currently open manual break. By default, if the break was started from an open shift, the shift is re-opened on the same job (mobile "Return to job"). Set isResumeShift: false to end the break without resuming (mobile "End shift").
Path Parameters
| Parameter | Type | Required | Description |
|---|---|---|---|
| timeClockId | integer | Yes | Time clock ID |
NomanualBreakIdon clock-outClock-out targets whichever manual break is currently open for the user, so the break type ID is not part of the path.
Request Body
| Field | Type | Required | Description |
|---|---|---|---|
| userId | integer | Yes | User's ID (must be assigned to the time clock) |
| timezone | string | No | Tz format. Defaults to the time clock setting |
| timestamp | integer | No | Break-end time in Unix seconds. Omitted = server-now. Max 12 hours in the past; not in the future; must be after the open break's start. |
| isResumeShift | boolean | No | Defaults to true (mobile "Return to job"). When true and the break came from a shift, the shift is re-opened on the same job. Set to false to end the break without resuming. |
| locationData | object | No | GPS coordinates and address |
| locationData.latitude | number | No | Latitude coordinate |
| locationData.longitude | number | No | Longitude coordinate |
| locationData.address | string | No | Address associated with the GPS data |
Open Break RequiredThe user must have an open manual break in this time clock. If there is no open break, the request is rejected with
NO_OPEN_BREAK.
Example: End Break and Return to Job (Default)
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/clock-out \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York"
}'Example: End Break Without Resuming the Shift
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/clock-out \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York",
"isResumeShift": false
}'Example: Retroactive Break End (Offline Mode)
curl --request POST \
--url https://api.connecteam.com/time-clock/v1/time-clocks/12345/manual-breaks/clock-out \
--header 'Content-Type: application/json' \
--header 'X-API-KEY: YOUR_API_KEY' \
--data '{
"userId": 9170357,
"timezone": "America/New_York",
"timestamp": 1748349420
}'The returned data.end.timestamp equals 1748349420.
Response: Break Ended and Shift Resumed
The resumedShift object describes the shift that was re-opened:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": {
"id": "break_activity_xyz789",
"end": {
"timestamp": 1748349420,
"timezone": "America/New_York"
},
"isResumeShift": true,
"resumedShift": {
"id": "shift-def456",
"userId": 9170357,
"start": {
"timestamp": 1748349420,
"timezone": "America/New_York",
"source": { "type": "api" }
},
"jobId": "job-123"
}
}
}Response: Break Ended, No Shift Resumed
Returned for a standalone break, or when isResumeShift: false:
{
"requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
"data": {
"id": "break_activity_xyz789",
"end": {
"timestamp": 1748349420,
"timezone": "America/New_York"
},
"isResumeShift": false
}
}Clock-Out Response Fields
| Field | Type | Description |
|---|---|---|
| requestId | string | Unique identifier for this API request |
| data.id | string | ID of the break activity that was ended |
| data.end.timestamp | integer | Break end time recorded by the server (Unix seconds) |
| data.end.timezone | string | Tz format timezone |
| data.isResumeShift | boolean | The actual outcome: true if a shift was re-opened, false otherwise (standalone break, or isResumeShift: false) |
| data.resumedShift | object | The shift that was re-opened. Present only when isResumeShift is true |
Integration Example
A complete "take a break and return to job" flow, plus offline flush:
class ManualBreakIntegration {
constructor(apiKey, timeClockId) {
this.apiKey = apiKey;
this.timeClockId = timeClockId;
this.baseUrl = 'https://api.connecteam.com/time-clock/v1/time-clocks';
}
get headers() {
return { 'X-API-KEY': this.apiKey, 'Content-Type': 'application/json' };
}
// Start a break. If the user is on a shift, the shift auto-closes.
async startBreak(userId, manualBreakId, { location, timestamp } = {}) {
const body = {
userId,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
};
if (location) body.locationData = location;
if (timestamp != null) body.timestamp = timestamp;
const res = await fetch(
`${this.baseUrl}/${this.timeClockId}/manual-breaks/${manualBreakId}/clock-in`,
{ method: 'POST', headers: this.headers, body: JSON.stringify(body) }
);
return res.json();
}
// End the open break. Defaults to returning to the source shift.
async endBreak(userId, { isResumeShift = true, location, timestamp } = {}) {
const body = {
userId,
timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
isResumeShift,
};
if (location) body.locationData = location;
if (timestamp != null) body.timestamp = timestamp;
const res = await fetch(
`${this.baseUrl}/${this.timeClockId}/manual-breaks/clock-out`,
{ method: 'POST', headers: this.headers, body: JSON.stringify(body) }
);
return res.json();
}
}
const mb = new ManualBreakIntegration('YOUR_API_KEY', 12345);
// On shift → tap "take break" → shift auto-closes, break opens
const started = await mb.startBreak(9170357, '8b8a161e-dfb5-42ac-bbf0-0448fc0c0c82');
console.log('Switched from shift:', started.data.isSwitchFromShift); // true
// Tap "return to job" → break closes, shift re-opens on the same job
const ended = await mb.endBreak(9170357); // isResumeShift defaults to true
console.log('Resumed shift:', ended.data.isResumeShift); // trueError Responses
| HTTP Status | Error Code | When |
|---|---|---|
400 | MANUAL_BREAKS_DISABLED | Manual breaks are not enabled for the time clock |
400 | MANUAL_BREAK_NOT_FOUND | The manualBreakId does not exist on the time clock or has been deleted |
400 | ALREADY_ON_BREAK | (Clock-in only.) The user is already on an open manual break |
400 | NO_OPEN_BREAK | (Clock-out only.) The user has no open manual break to end |
400 | MANDATORY_BREAK_TOO_SHORT | (Clock-out only.) The break is mandatory and its minimum duration has not elapsed |
400 | INVALID_TIMESTAMP_FUTURE | Supplied timestamp is in the future |
400 | INVALID_TIMESTAMP_TOO_OLD | timestamp is more than 12 hours in the past |
400 | INVALID_TIMESTAMP_BEFORE_START | (Clock-out only.) timestamp is at or before the open break's start time |
400 | OUTSIDE_GEOFENCE | Punch location is outside the configured geofence |
400 | LOCATION_REQUIRED | Location data is required by the time clock's geofence configuration |
400 | USER_NOT_ASSIGNED | The user is not assigned to the time clock |
409 | HAS_LOCKED_DAYS | The punch falls on a locked or approved timesheet day |
Notes
Important Considerations
- Switch attribution: when a break is started from a shift, the break is attributed to the shift's job for payroll. The closed shift's
endequals the break'sstart.- Out of scope: switching to a different job when ending a break, NFC tag handoff, and outside-geofence approval-request fallback are not supported by these endpoints.
- Per-time-clock state: break state is tracked independently per time clock. A shift open on a different time clock is not affected by a break here.
- For completed/historical breaks (older than 12 hours, or bulk imports), use Create time activities.
- See Real-Time Clocking for the shift-level clock-in/clock-out equivalents.
