Job Costing
This guide explains how to use the Friday API to track labor time by customer and project, then report on that time for job costing.
Prerequisites
- Plan: Timetracking or higher.
- Auth: An API key for the company, sent as
X-API-Keyon every request. - Setup: Customers and projects should already exist in Friday. The API can list, fetch, and update them, but new customer/project setup happens in the Friday product.
How Job Costing Works
Job costing in Friday is built from three pieces:
| Piece | Purpose |
|---|---|
| Customer | The job, customer, or job site you want to track labor against. |
| Project | A more specific subdivision under a customer, such as a phase, location, or workstream. |
| Time record | The employee's clock-in/clock-out span, optionally tagged with customer_id and project_id. |
When employees clock in against customers and projects, Friday can later group time by customer or project in timetrack reports.
Typical Flow
1. Sync customers and projects → GET /customers and GET /projects
2. Clock employees into a job → POST /time-records/clock-in
3. Clock employees out → POST /time-records/clock-out
4. Request job-costing report details → GET /timetrack/company
5. Optionally download reports → GET /timetrack/company/download
Step 1 — Sync Customers and Projects
Use the customer and project endpoints to keep your system aligned with the jobs configured in Friday.
| Action | Endpoint |
|---|---|
| List customers | GET /customers |
| Get customer | GET /customers/:customer_id |
| Update customer | PATCH /customers/:customer_id |
| List projects | GET /projects |
| Get project | GET /projects/:project_id |
| Update project | PATCH /projects/:project_id |
Projects belong to customers. If your app lets users choose a job before clocking in, show the customer first, then the available projects under that customer.
See the Customers and Projects guide for the full customer/project model.
Step 2 — Clock Into a Customer or Project
When creating a time record, include customer_id, project_id, or both.
POST /time-records/clock-in
{
"employee_id": 25,
"type": "work",
"customer_id": 3,
"project_id": 7,
"note": "Starting framing work"
}The resulting time record stores the job information:
{
"data": {
"time_record_id": 1042,
"type": "work",
"start": "2026-03-05T09:00:00.000Z",
"end": null,
"employee_id": 25,
"customer_id": 3,
"project_id": 7,
"customers": {
"customer_id": 3,
"name": "ABC Construction"
},
"projects": {
"project_id": 7,
"name": "Office Renovation"
}
}
}Some companies require a customer or project for every clock-in. If a required job is missing, the API returns a 400 error.
Disabled customers and projects cannot be used for new time records.
Step 3 — Switch Jobs During the Day
Use type: "switch" when an employee stays clocked in but moves to a different customer or project.
{
"employee_id": 25,
"type": "switch",
"customer_id": 9,
"project_id": 12,
"note": "Moving to afternoon job"
}A switch:
- Clocks out the current active work record.
- Creates a new work record with the new customer/project details.
- Returns the newly created time record.
switch is only a clock-in action. Stored records still have type: "work" or type: "break".
Step 4 — Get Job-Costing Breakdowns
Use timetrack report endpoints when you need totals grouped by job.
Company report
GET /timetrack/company?start=2026-03-01T00:00:00.000Z&end=2026-03-07T23:59:59.999Z&include_customer_reports=true&include_project_reports=trueEmployee report
GET /timetrack/employee/25?start=2026-03-01T00:00:00.000Z&end=2026-03-07T23:59:59.999Z&include_customer_reports=true&include_project_reports=true| Query parameter | Purpose |
|---|---|
start | Report start datetime, inclusive. |
end | Report end datetime, inclusive. |
timezone | Optional IANA timezone or numeric UTC offset. Defaults to America/New_York. |
include_customer_reports=true | Include time broken down by customer. |
include_project_reports=true | Include time broken down by project. |
include_days=true | Include per-day breakdowns. |
include_time_records=true | Include raw time records behind the totals. |
Example customer breakdown:
{
"customer_reports": [
{
"customer": {
"customer_id": 3,
"name": "ABC Construction"
},
"report": {
"regular_hours": 40,
"overtime_hours": 3,
"total_hours": 43
}
},
{
"customer": {
"customer_id": 9,
"name": "XYZ Plumbing"
},
"report": {
"regular_hours": 12,
"overtime_hours": 0,
"total_hours": 12
}
}
]
}Step 5 — Download Job-Costing Reports
Use the company download endpoint when you need a PDF or CSV export.
GET /timetrack/company/download
Required query parameters:
| Parameter | Purpose |
|---|---|
start | Report start datetime, inclusive. |
end | Report end datetime, inclusive. |
type | Output format: pdf, periodTotalsCsv, dailyTotalsCsv, or timeRecordsCsv. |
Useful optional parameters:
| Parameter | Purpose |
|---|---|
timezone | Timezone for report grouping. |
timetype | Format time values as decimal or minutes. |
employeeIds | Comma-separated employee IDs to include. |
pay_schedule_group_id | Restrict the report to one pay schedule group. |
Job Geofencing
If the company uses job geofencing, clock-in and clock-out may require coordinates. The applicable fence comes from the customer/project on clock-in, or from the active time record on clock-out.
Send coordinates as:
latitude,longitude
Example:
{
"employee_id": 25,
"customer_id": 3,
"project_id": 7,
"start_coordinates": "40.7128,-74.0060"
}If coordinates are missing or outside the allowed perimeter, the API rejects the request with a 400 error.
Try It Out
Use the API Reference to test a job-costing flow in sandbox:
Common Pitfalls
- Using disabled jobs — Disabled customers and projects cannot be used for new clock-ins.
- Forgetting to include customer/project report flags — Job-costing breakdowns only appear when
include_customer_reports=trueorinclude_project_reports=true. - Expecting
switchto appear in reports — Switches create normalworkrecords; they do not create a separate stored record type. - Missing geofence coordinates — If a job requires geofencing, include coordinates on clock-in and clock-out.
- Mixing environments — Sandbox and production have separate customers, projects, time records, and API keys.
Quick Reference
| Action | Method | Path |
|---|---|---|
| List customers | GET | /customers |
| List projects | GET | /projects |
| Clock into a job | POST | /time-records/clock-in |
| Switch jobs | POST | /time-records/clock-in with type: "switch" |
| Clock out | POST | /time-records/clock-out |
| Company job-costing report | GET | /timetrack/company |
| Employee job-costing report | GET | /timetrack/employee/:employee_id |
| Download report | GET | /timetrack/company/download |
Updated about 9 hours ago
