Working with Timesheets
Overview
The Timesheet API provides a set of endpoints that allow you to manage and track employee work hours, including detailed time entries and their statuses. Through this API, you can retrieve, create, update, and manage timesheets submitted by your employees.
Key features include:
- Listing Timesheets: Retrieve all timesheets associated with your company.
- Show Timesheet: Access detailed information about a specific timesheet by its ID.
- Time Tracking: Breakdown shifts into various categories (e.g., regular hours, overtime, weekend, night hours).
- Special Time Types: Automatically handle time-off and public holiday tracking.
- Approve or Decline Timesheet: Manage timesheets by approving or sending them back for revisions.
Prerequisites
Before you get started, ensure that you have an active employment in your company with timesheets already created.
Timesheet.submitted webhook
Every time an employee submits a timesheet for review, the timesheet.submitted
webhook is triggered notifying the company owners and admins that there are pending timesheets.
ℹ️ This webhook is not triggered in case a timesheet is automatically approved. See the section at the bottom to learn about automatically approved timesheets.
List timesheets
The API provides an endpoint to retrieve a list of all timesheets associated with your company. You can filter the results by their status:open
, submitted
, in_calibration
, and processed
, or sort the list in a specific order.
This allows you to view all relevant timesheets linked to your organization. Detailed descriptions of the fields returned by this endpoint are provided in the next section.
Show timesheet
The API provides an endpoint to retrieve a specific timesheet by its ID. Below is an example of the response:
{
"data":{
"timesheet":{
"approval_required":true,
"break_hours":{
"hours":35,
"minutes":13
},
"country_code":"PRT",
"employment_id":"663e0b79-c893-45ff-a1b2-f6dcabc098b5",
"end_date":"2021-07-01",
"holiday_hours":{
"hours":35,
"minutes":13
},
"id":"663e0b79-c893-45ff-a1b2-f6dcabc098b5",
"night_hours":{
"hours":35,
"minutes":13
},
"notes":"Some notes",
"on_call_hours":{
"hours":35,
"minutes":13
},
"overtime_hours":{
"hours":35,
"minutes":13
},
"regular_hours":{
"hours":35,
"minutes":13
},
"start_date":"2021-07-01",
"status":"submitted",
"submitted_at":"2021-07-15T18:18:17Z",
"time_tracking":[
...
],
"total_hours":{
"hours":35,
"minutes":13
},
"weekend_hours":{
"hours":35,
"minutes":13
}
}
}
}
- approval_required: A boolean indicating whether employer approval is required for this timesheet.
- break_hours: An object containing hours and minutes, representing the total break hours in the timesheet.
- holiday_hours: An object containing hours and minutes, representing the total holiday hours in the timesheet.
- night_hours: An object containing hours and minutes, representing the total night hours in the timesheet.
- on_call_hours: An object containing hours and minutes, representing the total on-call hours in the timesheet.
- overtime_hours: An object containing hours and minutes, representing the total overtime hours in the timesheet.
- regular_hours: An object containing hours and minutes, representing the total regular hours in the timesheet.
- weekend_hours: An object containing hours and minutes, representing the total weekend hours in the timesheet.
- total_hours: An object containing hours and minutes, representing the total number of hours recorded in the timesheet.
- country_code: The country code associated with the timesheet.
- employment_id: The employment ID associated with the timesheet.
- start_date: The start date of the timesheet period.
- end_date: The end date of the timesheet period.
- id: The unique identifier for the timesheet.
- notes: Additional notes attached to the timesheet.
- status: The current status of the timesheet. Possible values are:
open
,submitted
,approved
,in_calibration
, orprocessed
.open
: The initial status when employees can edit time tracking and all*_hours
fields associated with the timesheet. If a timesheet is never submitted for review, it will remain in theopen
state.submitted
: Indicates that the employee has submitted the timesheet for review and theapproval_required
flag is set to true.approved
: Indicates that the timesheet has been approved.in_calibration
: This status means employees can edit time tracking but only if the timesheet was previously submitted and sent back for amendments. When the status changes toin_calibration
, all automatic fields (submitted_at
,submitted_by
,approved_at
,approved_by
) are cleared and a new boolean flagcalibrated
is added which is set to true.processed
: Indicates that the timesheet has been included in the payroll run and is considered paid. At this point, the timesheet will be locked and can no longer be edited.
- submitted_at: The timestamp indicating when the timesheet was submitted.
- time_trackings: The following section explains this field in detail.
TimeTracking
This object represents the first level of breakdown within a timesheet. It provides detailed information about each shift recorded in the timesheet. For example, a single TimeTracking
object might look like this:
"time_tracking":[
{
"clock_in":"2021-07-15T18:18:17Z",
"clock_out":"2021-07-15T18:18:17Z",
"has_holiday_hours":false,
"has_night_hours":false,
"has_weekend_hours":false,
"holiday_hours":{
"hours":35,
"minutes":13
},
"night_hours":{
"hours":35,
"minutes":13
},
"notes":"Time tracking project.",
"time_breakdown":{
"day":{
"holiday":{
"hours":35,
"minutes":13
},
"regular":{
"hours":35,
"minutes":13
},
"weekend":{
"hours":35,
"minutes":13
}
},
"night":{
"holiday":{
"hours":35,
"minutes":13
},
"regular":{
"hours":35,
"minutes":13
},
"weekend":{
"hours":35,
"minutes":13
}
}
},
"timezone":"Etc/UTC",
"total_hours":{
"hours":35,
"minutes":13
},
"type":"regular_hours",
"weekend_hours":{
"hours":35,
"minutes":13
}
}
],
This object has the following fields:
- type: Specifies the type of time tracking. Possible values are:
regular_hours
,overtime
,on_call
,break
,time_off
,public_holiday
. - timezone: The timezone associated with the time tracking entry.
- notes: Additional notes related to the time tracking entry.
- total_hours: An object containing hours and minutes, representing the total recorded hours in the time tracking entry.
- weekend_hours: An object containing hours and minutes, representing the total weekend hours in the time tracking entry.
- holiday_hours: An object containing hours and minutes, representing the total holiday hours in the time tracking entry.
- night_hours: An object containing hours and minutes, representing the total night hours in the time tracking entry.
- clock_in: The date and time when the shift started (clock-in time).
- clock_out: The date and time when the shift ended (clock-out time).
- has_holiday_hours: A boolean indicating whether the time tracking entry includes holiday hours.
- has_night_hours: A boolean indicating whether the time tracking entry includes night hours.
- has_weekend_hours: A boolean indicating whether the time tracking entry includes weekend hours.
- time_breakdown: An object providing a detailed breakdown of the time tracking entry. It categorizes time into day and night segments and further subdivides these into
holiday
,regular
, andweekend
hours.
ℹ️ Time tracking varies depending on the country. For example, the definition of what counts as a holiday, night shift, and weekend hours is different for every country and is automatically processed by Remote.
In general, for a single time_tracking
object, we would have three indicators: has_holiday_hours
, has_night_hours
, and has_weekend_hours
. In addition to these indicators, the type could be one of the following break
, on_call
, overtime
, regular_hours
, time_off
, and public_holiday
.
An API user can leverage both the type and the fields hours and minutes of holiday_hours
, weekend_hours
and night_hours
to determine all possible scenarios.
To further explain the logic that is used to determine how each entry is categorized, we can take a look at a more complex timeTracking scenario:
{
"type":"overtime",
"timezone":"Canada/Montreal",
"notes":"Complex example",
"total_hours":{
"minutes":0,
"hours":16
},
"holiday_hours":{
"minutes":0,
"hours":0
},
"weekend_hours":{
"minutes":0,
"hours":1
},
"night_hours":{
"minutes":0,
"hours":4
},
"clock_in":"2024-06-23T14:00:00Z",
"clock_out":"2024-06-23T16:00:00Z",
"has_holiday_hours":false,
"has_night_hours":true,
"has_weekend_hours":true,
"time_breakdown":{
"day":{
"regular":{
"minutes":0,
"hours":11
},
"holiday":{
"minutes":0,
"hours":0
},
"weekend":{
"minutes":0,
"hours":0
}
},
"night":{
"regular":{
"minutes":0,
"hours":4
},
"holiday":{
"minutes":0,
"hours":0
},
"weekend":{
"minutes":0,
"hours":1
}
}
}
}
In this example, the type
is set to overtime
, and the TimeTracking
entry includes night hours and weekend hours, with a total of 16 hours recorded.
Looking deeper into the time_breakdown
, the composition of these 16 hours is as follows:
- 1 hour of overtime weekend night hours.
- 4 hours of overtime night hours.
- 11 hours of overtime regular hours.
Special cases
There are 2 special types of time tracking:
- public_holiday: Used when the time off that generated the time tracking entry corresponds to a holiday (either automatic or manually recorded).
- time_off: Used for all other types of time-off requests, such as PTO, sick leave, etc.
For these special types, it is possible for time tracking entries to overlap. For example, if there is a public holiday on December 25th and an employee works 2 hours of overtime on that day, the system will create:
- One time tracking entry covering the entire day for the public holiday.
- And another entry for the 2 hours overtime worked on the same day.
Special types cannot be manually tracked. They are automatically synced when being added, canceled, or declined.
Approve Timesheet
This endpoint is used to approve a submitted timesheet. It sends a simple response with all the details necessary to approve the entry.
{
"data":{
"timesheet":{
"approval_required":true,
"country_code":"PRT",
"employment_id":"663e0b79-c893-45ff-a1b2-f6dcabc098b5",
"end_date":"2021-07-01",
"id":"663e0b79-c893-45ff-a1b2-f6dcabc098b5",
"notes":"Some notes",
"start_date":"2021-07-01",
"status":"submitted",
"submitted_at":"2021-07-15T18:18:17Z"
}
}
}
ℹ️ You can only use this endpoint to approve a timesheet if the
approval_required
flag is set to true.
Automatically approved timesheets
A timesheet is automatically approved if either of the following conditions are met:
- The submitted week only includes regular hours - meaning there was no overtime, no night shifts, no weekend hours worked, etc.
- The
approval_required
flag is not set while submitting the request.
Any timesheet that has been automatically approved will have the default user listed in the approved_by
field.
Send back a Timesheet
This endpoint is used to send back a timesheet for review or modification to the employee.
Here is an example of the response:
{
"data":{
"timesheet":{
"id":"663e0b79-c893-45ff-a1b2-f6dcabc098b5",
"sent_back":true,
"sent_back_reason":"Please review the timesheet.",
"status":"submitted"
}
}
}
- sent_back: A boolean indicating whether this timesheet was sent back by the reviewer.
- sent_back_reason: A string providing the reason why the timesheet was sent back.
ℹ️ If the employer sends the timesheet back for amendments, its status changes to
in_calibration
, and the fieldssent_back
andsent_back_by
will be flagged to indicate this action.
Updated 8 days ago