> ## Documentation Index
> Fetch the complete documentation index at: https://docs.paypunch.io/llms.txt
> Use this file to discover all available pages before exploring further.

# Submit Timesheet

> POST /api/v1/employee/timesheet/submit — submit a pay period's timesheet for approval and mark the period SUBMITTED.

Submit the authenticated employee's timesheet for a given pay period. This marks
the employee's `PENDING` entries as `APPROVED` and sets the pay period status to
`SUBMITTED`.

```http theme={null}
POST /api/v1/employee/timesheet/submit
```

**Authentication:** requires an **employee** JWT. The employee is taken from the
token's `userId`.

## Request body

<ParamField body="payPeriodId" type="string" required>
  UUID of the pay period to submit. Must belong to the employee's company
  (`403` `Access denied` otherwise).
</ParamField>

## Behavior & preconditions

The request is rejected if any of the following hold:

| Status | `error`                          | Condition                                                                                              |
| ------ | -------------------------------- | ------------------------------------------------------------------------------------------------------ |
| `404`  | `Employee not found or inactive` | Token user missing or deactivated.                                                                     |
| `404`  | `Pay period not found`           | No pay period with that `id`.                                                                          |
| `403`  | `Access denied`                  | Pay period belongs to a different company.                                                             |
| `400`  | `Pay period locked`              | The pay period is `locked`.                                                                            |
| `400`  | `Already submitted`              | Status is already `SUBMITTED`, `APPROVED`, `PAID`, or `CLOSED`.                                        |
| `400`  | `Open time entries`              | The employee has entries with no `clockOut` (their `id`/`clockIn` are returned in `data.openEntries`). |
| `400`  | `No time entries`                | The employee has no entries in this pay period.                                                        |

On success, the employee's `PENDING` entries in the period are updated to
`APPROVED`, the pay period status becomes `SUBMITTED`, and the response includes
the updated period, the entry count, and computed totals.

<Warning>
  On submission, this endpoint auto-approves the employee's own `PENDING`
  entries (sets them to `APPROVED`) and flips the whole pay period to
  `SUBMITTED`. There is no per-employee submission state — submitting affects
  the shared pay period record.
</Warning>

## Response

<ResponseField name="data.payPeriod" type="object">
  The updated pay period (now `status: "SUBMITTED"`).
</ResponseField>

<ResponseField name="data.timeEntriesCount" type="integer">
  Number of the employee's entries in this pay period.
</ResponseField>

<ResponseField name="data.totals" type="object">
  `totalHours`, `regularHours`, `overtimeHours` summed across those entries.
</ResponseField>

<ResponseField name="data.message" type="string">
  `Timesheet submitted successfully`.
</ResponseField>

## Examples

<CodeGroup>
  ```bash cURL theme={null}
  curl -X POST https://app.paypunch.io/api/v1/employee/timesheet/submit \
    -H "Authorization: Bearer <employee-token>" \
    -H "Content-Type: application/json" \
    -d '{ "payPeriodId": "pp_01..." }'
  ```

  ```json Response (200) theme={null}
  {
    "success": true,
    "data": {
      "payPeriod": {
        "id": "pp_01...",
        "status": "SUBMITTED",
        "locked": false
      },
      "timeEntriesCount": 10,
      "totals": { "totalHours": 80, "regularHours": 78, "overtimeHours": 2 },
      "message": "Timesheet submitted successfully"
    }
  }
  ```

  ```json Open entries (400) theme={null}
  {
    "success": false,
    "error": "Open time entries",
    "message": "Please clock out of all time entries before submitting your timesheet",
    "data": {
      "openEntries": [ { "id": "t9...", "clockIn": "2026-06-17T13:00:00.000Z" } ]
    }
  }
  ```
</CodeGroup>
