Timetracking

This guide explains how the Friday API tracks employee time with time records, how clock-in and clock-out work, what a switch is, and how to read time records and timetrack reports.

Prerequisites

  • Plan: Timetracking or higher.
  • Auth: An API key for the company, sent as X-API-Key on every request.
  • Employees: The employee must belong to the company associated with your API key and must be active.

What Is a Time Record?

A time record represents one continuous span of employee time. It starts when an employee clocks in and ends when they clock out.

An active time record has end: null.

{
  "time_record_id": 1042,
  "type": "work",
  "start": "2026-03-05T09:00:00.000Z",
  "end": null,
  "employee_id": 25,
  "customer_id": 3,
  "project_id": 7,
  "note": "Starting morning shift"
}
FieldMeaning
typeEither work or break.
startClock-in timestamp.
endClock-out timestamp, or null while the record is active.
employee_idEmployee whose time is being tracked.
customer_idOptional customer/job associated with the time.
project_idOptional project associated with the time.
note / end_noteOptional notes captured at clock-in or clock-out.

Typical Flow

1. Clock in for work        → POST /time-records/clock-in
2. Optionally start break  → POST /time-records/clock-in with type: "break"
3. Resume or switch work   → POST /time-records/clock-in with type: "work" or "switch"
4. Clock out               → POST /time-records/clock-out
5. Read history/reports    → GET /time-records or /timetrack/*

The API keeps only one active record per employee at a time. When a new valid clock-in starts a different type of record, the existing active record is automatically ended first.


Clock In

POST /time-records/clock-in

Clock-in starts a new active time record for an employee. The only required field is employee_id.

If type is omitted, the API defaults to work.

{
  "employee_id": 25,
  "type": "work",
  "customer_id": 3,
  "project_id": 7,
  "note": "Starting morning shift",
  "start_coordinates": "40.7128,-74.0060",
  "start_location": "Job site - Main St"
}
FieldRequired?Notes
employee_idYesEmployee to clock in.
typeOptionalwork, break, or switch. Defaults to work.
customer_idOptionalCustomer/job to associate with the record. May be required by company settings.
project_idOptionalProject to associate with the record. May be required by company settings.
noteOptionalClock-in note.
start_coordinatesConditionalRequired when job geofencing applies. Format: latitude,longitude.
start_locationOptionalHuman-readable clock-in location label.

Conflicts and validation

  • If the employee already has an active record of the same type, the API returns 409.
  • If the employee starts a different type of record, the existing record is automatically clocked out first.
  • If company settings require a customer or project and neither is provided, the API returns 400.
  • If a specified customer or project is disabled, the API returns 400.
  • If job geofencing applies and coordinates are missing, invalid, or outside the allowed perimeter, the API returns 400.

Breaks

Use type: "break" when an employee pauses work but remains in the middle of their day.

{
  "employee_id": 25,
  "type": "break",
  "note": "Lunch break"
}

An employee must already have an active work record before starting a break. If they are not clocked in, the API returns:

{
  "error": "Employee must be clocked in to take a break"
}

When the break starts, the active work record is ended and a break record begins.


Switches

Use type: "switch" when an employee stays clocked in but changes what they are working on, such as moving from one customer or project to another.

{
  "employee_id": 25,
  "type": "switch",
  "customer_id": 8,
  "project_id": 12,
  "note": "Moving to afternoon job"
}

A switch:

  1. Automatically clocks out the current active work record.
  2. Creates a new work record with the new customer/project/note details.
  3. Returns the newly created time record.

Important: switch is a request action, not a stored time record type. The new record is stored and returned as type: "work".


Clock Out

POST /time-records/clock-out

Clock-out ends the employee's current active time record.

{
  "employee_id": 25,
  "end_note": "Finished for the day",
  "end_coordinates": "40.7128,-74.0060",
  "end_location": "Job site - Main St"
}
FieldRequired?Notes
employee_idYesEmployee to clock out.
end_noteOptionalClock-out note.
end_coordinatesConditionalRequired when job geofencing applies to the active record.
end_locationOptionalHuman-readable clock-out location label.

If the employee has no active time record, the API returns 409.


Customers, Projects, and Geofencing

Time records can be associated with a customer, a project, or both. Companies may require a customer or project on clock-in. Use the Customers and Projects guide for more detail on how those objects relate.

If job geofencing applies, clock-in and clock-out require coordinates in latitude,longitude format. The API enforces the same customer/project geofencing rules configured in Friday.

Example coordinate value:

40.7128,-74.0060

If coordinates are missing or outside the allowed perimeter, the request is rejected with a clear error message.


Reading Time Records

GET /time-records

Returns a paginated list of time records sorted by start time, newest first.

Query parameterPurpose
page, per_pagePagination.
employee_idFilter by employee.
typeFilter by work or break.
start_afterOnly records that started on or after this timestamp.
start_beforeOnly records that started on or before this timestamp.
active=trueOnly currently active records.

GET /time-records/:time_record_id

Returns one time record with additional detail fields such as coordinates, expiration, note image URLs, and employee summary.


Timetrack Reports

Use timetrack report endpoints when you need totals rather than raw records.

ActionEndpoint
Company reportGET /timetrack/company
Employee reportGET /timetrack/employee/:employee_id
Download reportGET /timetrack/company/download

Company and employee reports require start and end query parameters. Optional include_* parameters let you include day breakdowns, raw time records, customer reports, and project reports.

Downloads support PDF and CSV outputs.


Try It Out

Use the API Reference to test a full time tracking flow in sandbox:


Common Pitfalls

  • Starting a break before work — A break requires an active work record.
  • Using switch as a record type filterswitch is only accepted in the clock-in request. Stored records are work or break.
  • Missing customer/project requirements — Some companies require customer or project selection for clock-in.
  • Disabled customer or project — Disabled jobs cannot be used for new time records.
  • Missing geofence coordinates — If geofencing applies, send start_coordinates or end_coordinates as required.
  • Wrong environment — Sandbox and production keys are separate, and each key must be used with the matching base URL.

Quick Reference

ActionMethodPath
List time recordsGET/time-records
Get time recordGET/time-records/:time_record_id
Clock inPOST/time-records/clock-in
Clock outPOST/time-records/clock-out
Company time reportGET/timetrack/company
Employee time reportGET/timetrack/employee/:employee_id
Download time reportGET/timetrack/company/download