---
updatedAt: 2026-06-24T13:25:39.000Z
---

Fetch the complete documentation index at: https://developer.connecteam.com/llms.txt. Use this file to discover all available pages before exploring further.

# Real-Time Clocking

Clock in and clock out users in real-time. By default, the server captures the punch time when the request is received. Pass an optional `timestamp` (Unix seconds) to record a punch that already happened — typically when a physical clock device flushes queued punches after reconnecting from offline mode.

## Endpoints

| Method | Endpoint                                           | Description      |
| :----- | :------------------------------------------------- | :--------------- |
| POST   | /time-clock/v1/time-clocks/{timeClockId}/clock-in  | Clock in a user  |
| POST   | /time-clock/v1/time-clocks/{timeClockId}/clock-out | Clock out a user |

> 📘 Taking a break?
>
> To start or end a **manual break** (with automatic shift → break → shift transitions), see [Manual Break Clocking](https://developer.connecteam.com/docs/time-clock-manual-break-clocking).

***

## Offline Mode (Retroactive Punches)

Physical clock devices (kiosks, NFC stations, biometric terminals) usually call clock-in/out the moment an employee punches. When a device **loses connectivity**, punches queue locally. On reconnect, pass the **original punch time** via `timestamp` so the timesheet reflects when the employee actually clocked — not when the API call arrived.

> 👍 Prefer clock-in/out over time activities for offline sync
>
> **Use clock-in/out with `timestamp`, not Create time activities.** Time activities write a *completed* shift. If the employee later clocks out online via the normal clock-out flow, there is no open shift to close. Retroactive clock-in/out preserves the open-shift lifecycle.

> 📘 Timestamp rules (when `timestamp` is 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 shift's clock-in time
> * Clock-out only: the punch day must **not** be locked or approved
> * When omitted, behavior is unchanged (server captures time at request receipt)

Typical offline flush order for one shift:

1. `POST .../clock-in` with the queued clock-in `timestamp`
2. `POST .../clock-out` with the queued clock-out `timestamp`

For punches older than 12 hours, use [Create time activities](https://developer.connecteam.com/docs/time-clock-time-activities) instead.

***

## Clock In

Record the start of a work period. By default the start time is captured when the call is executed. Pass an optional `timestamp` to record a clock-in that occurred earlier.

### Path Parameters

| Parameter   | Type    | Required | Description   |
| :---------- | :------ | :------- | :------------ |
| timeClockId | integer | Yes      | Time clock ID |

### Request Body

| Field            | Type    | Required    | Description                                                                                                                          |
| :--------------- | :------ | :---------- | :----------------------------------------------------------------------------------------------------------------------------------- |
| userId           | integer | Yes         | User's ID (must be assigned to the time clock)                                                                                       |
| jobId            | string  | Conditional | Job or sub-job ID (required if job enforcement is enabled)                                                                           |
| timezone         | string  | No          | Tz format (e.g., America/New\_York). Defaults to time clock setting                                                                  |
| schedulerShiftId | string  | No          | Link to a scheduled shift                                                                                                            |
| locationData     | object  | No          | GPS coordinates and address                                                                                                          |
| timestamp        | integer | No          | Clock-in time in Unix seconds. Omitted = server-now. Max 12 hours in the past; not in the future. Use when flushing offline punches. |

> ⚠️ User Assignment Required
>
> The user must be **assigned to the specified time clock** before they can clock in. Use the Users API to manage assignments.

### Example: Basic Clock In

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-in \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357
  }'
```

### Example: Clock In with Job

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-in \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357,
    "jobId": "job-123",
    "timezone": "America/New_York"
  }'
```

### Example: Clock In with Location

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-in \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357,
    "jobId": "job-123",
    "timezone": "America/New_York",
    "locationData": {
      "address": "123 Main St, New York, NY 10001",
      "latitude": 40.7128,
      "longitude": -74.0060
    }
  }'
```

### Example: Clock In with Scheduler Shift

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-in \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357,
    "schedulerShiftId": "sched-shift-789",
    "timezone": "America/New_York"
  }'
```

### Example: Retroactive Clock In (Offline Mode)

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-in \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357,
    "jobId": "job-123",
    "timezone": "America/New_York",
    "timestamp": 1748345820
  }'
```

The returned `data.shift.start.timestamp` equals `1748345820`.

### Response

```json
{
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": {
    "shift": {
      "id": "shift-abc123",
      "userId": 9170357,
      "start": {
        "timestamp": 1704110400,
        "timezone": "America/New_York",
        "locationData": {
          "address": "123 Main St, New York, NY 10001",
          "latitude": 40.7128,
          "longitude": -74.0060
        },
        "source": {
          "type": "api"
        }
      },
      "jobId": "job-123",
      "schedulerShiftId": null,
      "createdAt": 1704110400,
      "modifiedAt": 1704110400
    }
  }
}
```

***

## Clock Out

Record the end of a work period. By default the end time is captured when the call is executed. Pass an optional `timestamp` to record a clock-out that occurred earlier. Associates with the user's current open shift.

### Path Parameters

| Parameter   | Type    | Required | Description   |
| :---------- | :------ | :------- | :------------ |
| timeClockId | integer | Yes      | Time clock ID |

### Request Body

| Field        | Type    | Required | Description                                                                                                                                                                    |
| :----------- | :------ | :------- | :----------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| userId       | integer | Yes      | User's ID                                                                                                                                                                      |
| timezone     | string  | No       | Tz format. Defaults to time clock setting                                                                                                                                      |
| timestamp    | integer | No       | Clock-out time in Unix seconds. Omitted = server-now. Max 12 hours in the past; not in the future; must be after the open shift's clock-in. Use when flushing offline punches. |
| locationData | object  | No       | GPS coordinates and address                                                                                                                                                    |

> 📝 Open Shift Required
>
> The user must have an **open shift** (clocked in but not out) in this time clock. The clock-out will be associated with the most recent open shift.

### Example: Basic Clock Out

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-out \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357
  }'
```

### Example: Clock Out with Location

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-out \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357,
    "timezone": "America/New_York",
    "locationData": {
      "address": "456 Oak Ave, New York, NY 10002",
      "latitude": 40.7145,
      "longitude": -74.0055
    }
  }'
```

### Example: Retroactive Clock Out (Offline Mode)

```bash
curl --request POST \
  --url https://api.connecteam.com/time-clock/v1/time-clocks/12345/clock-out \
  --header 'Content-Type: application/json' \
  --header 'X-API-KEY: YOUR_API_KEY' \
  --data '{
    "userId": 9170357,
    "timezone": "America/New_York",
    "timestamp": 1748374620
  }'
```

The returned `data.shift.end.timestamp` equals `1748374620`.

### Response

```json
{
  "requestId": "a1b2c3d4-e5f6-7890-abcd-ef1234567890",
  "data": {
    "shift": {
      "id": "shift-abc123",
      "userId": 9170357,
      "start": {
        "timestamp": 1704110400,
        "timezone": "America/New_York",
        "source": {
          "type": "api"
        }
      },
      "end": {
        "timestamp": 1704139200,
        "timezone": "America/New_York",
        "locationData": {
          "address": "456 Oak Ave, New York, NY 10002",
          "latitude": 40.7145,
          "longitude": -74.0055
        },
        "source": {
          "type": "api"
        }
      },
      "jobId": "job-123",
      "createdAt": 1704110400,
      "modifiedAt": 1704139200
    }
  }
}
```

***

## Integration Example

Complete clock-in/clock-out workflow, including flushing an offline queue:

```javascript
class TimeClockIntegration {
  constructor(apiKey, timeClockId) {
    this.apiKey = apiKey;
    this.timeClockId = timeClockId;
    this.baseUrl = 'https://api.connecteam.com/time-clock/v1/time-clocks';
  }

  async clockIn(userId, { jobId, location, timestamp } = {}) {
    const body = {
      userId,
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    };
    if (jobId) body.jobId = jobId;
    if (location) body.locationData = location;
    if (timestamp != null) body.timestamp = timestamp;

    const response = await fetch(`${this.baseUrl}/${this.timeClockId}/clock-in`, {
      method: 'POST',
      headers: { 'X-API-KEY': this.apiKey, 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
    });
    return response.json();
  }

  async clockOut(userId, { location, timestamp } = {}) {
    const body = {
      userId,
      timezone: Intl.DateTimeFormat().resolvedOptions().timeZone,
    };
    if (location) body.locationData = location;
    if (timestamp != null) body.timestamp = timestamp;

    const response = await fetch(`${this.baseUrl}/${this.timeClockId}/clock-out`, {
      method: 'POST',
      headers: { 'X-API-KEY': this.apiKey, 'Content-Type': 'application/json' },
      body: JSON.stringify(body),
    });
    return response.json();
  }

  /** Flush queued punches after device reconnects (oldest first). */
  async flushOfflineQueue(events) {
    for (const event of events) {
      if (event.type === 'clock-in') {
        await this.clockIn(event.userId, {
          jobId: event.jobId,
          location: event.location,
          timestamp: event.timestamp,
        });
      } else if (event.type === 'clock-out') {
        await this.clockOut(event.userId, {
          location: event.location,
          timestamp: event.timestamp,
        });
      }
    }
  }
}

// Live punch (no timestamp — server-now)
const tc = new TimeClockIntegration('YOUR_API_KEY', 12345);
await tc.clockIn(9170357, { jobId: 'job-123' });
await tc.clockOut(9170357);

// Offline flush after reconnect
await tc.flushOfflineQueue([
  { type: 'clock-in', userId: 9170357, jobId: 'job-123', timestamp: 1748345820 },
  { type: 'clock-out', userId: 9170357, timestamp: 1748374620 },
]);
```

***

## Error Responses

| HTTP Status | Error Code                          | When                                                                         |
| :---------- | :---------------------------------- | :--------------------------------------------------------------------------- |
| `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_CLOCK_IN` | (Clock-out only.) `timestamp` is at or before the open shift's clock-in time |
| `409`       | `HAS_LOCKED_DAYS`                   | `timestamp` falls on a locked or approved timesheet day                      |
| `400`       | —                                   | User not assigned to the time clock                                          |
| `400`       | —                                   | User already has an open shift (clock-in)                                    |
| `400`       | `NO_OPEN_SHIFT`                     | (Clock-out only.) No open shift to close                                     |
| `400`       | `JOB_REQUIRED`                      | (Clock-in only.) Job ID required by time clock settings                      |
| `400`       | `OPEN_BREAK`                        | (Clock-in only.) User is clocked into a manual break                         |
| `400`       | `OUTSIDE_GEOFENCE`                  | Punch location is outside the configured geofence                            |

All pre-existing error codes for these endpoints remain unchanged.

***

[Clock In API Reference](https://developer.connecteam.com/reference/clock_user_in_time_clock_v1_time_clocks__timeclockid__clock_in_post) · [Clock Out API Reference](https://developer.connecteam.com/reference/clock_user_out_time_clock_v1_time_clocks__timeclockid__clock_out_post)