REST endpoints for time in ServFlo: 17 operations with parameters, request and response fields, permissions and curl examples.
Base URL: https://app.servflo.ai/api. Every call needs Authorization: Bearer sfk_… (Authentication); {organizationId} ($ORGANIZATION_ID in the examples) is your business's id.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
entries[].activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
entries[].startedAt
string (date-time)
entries[].endedAt
string (date-time) or null
entries[].note
string or null
entries[].source
enum
One of CLOCK, MANUAL, AUTO.
entries[].status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
The day, YYYY-MM-DD. Defaults to today in the organization's timezone.
timeZone
query
string
No
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.
The non-job time running now, if any. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
running
array of object
running[].id
string
running[].organizationId
string
running[].userId
string
running[].technicianId
string or null
running[].jobId
string or null
running[].kind
enum
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
running[].activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
running[].startedAt
string (date-time)
running[].endedAt
string (date-time) or null
running[].note
string or null
running[].source
enum
One of CLOCK, MANUAL, AUTO.
running[].status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
running[].editReason
string or null
running[].editedByUserId
string or null
running[].approvedByUserId
string or null
running[].approvedAt
string (date-time) or null
running[].createdAt
string (date-time)
running[].updatedAt
string (date-time)
running[].job
object or null
running[].job.id
string
running[].job.identifier
string
running[].technician
object or null
running[].technician.id
string
running[].technician.name
string
running[].technician.color
string
running[].userName
string or null
running[].minutes
integer
Whole minutes (a running entry counts to now).
running[].date
string
The day it started, in the requested timezone.
today
object
today.SHIFT
integer
today.JOB
integer
today.TRAVEL
integer
today.BREAK
integer
today.ACTIVITY
integer
today.paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
POST /organizations/{organizationId}/time/activity/start
Starts non-job work for the caller (ACTIVITY with activity: the shop, the supply house, a meeting, training, the vehicle, paperwork or other), as ServiceTitan's non-job events. Needs a running shift (409 otherwise). Stops a break, travel or another activity; the same activity again returns the running one. Heading to or starting a job ends it. Paid time, shown per activity on the timesheet.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
Time entries newest first, filtered by person (userId), technician, job, kind, status and days (from/to, YYYY-MM-DD in timeZone), paged with limit/offset and a total. Technicians always get only their own entries. Read-only.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
status
query
enum
No
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
from
query
string
No
A calendar date in the business's own calendar, YYYY-MM-DD.
to
query
string
No
A calendar date in the business's own calendar, YYYY-MM-DD.
timeZone
query
string
No
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
items[].activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
items[].startedAt
string (date-time)
items[].endedAt
string (date-time) or null
items[].note
string or null
items[].source
enum
One of CLOCK, MANUAL, AUTO.
items[].status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
Records finished time with a reason (source MANUAL): for the caller, or (office roles with time.manage) for userId or technicianId (a technician linked to an account). It may not overlap another entry of the same kind for that person (409), start in the future or run over 24 hours (400). Technicians may add only their own time, on their own jobs. Returns the entry.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
startedAt
string (date-time)
Yes
An instant as an ISO 8601 date-time with offset, e.g. 2026-10-05T08:30:00-05:00.
endedAt
string (date-time)
Yes
An instant as an ISO 8601 date-time with offset, e.g. 2026-10-05T08:30:00-05:00.
note
string or null
No
Up to 2000 characters.
reason
string
Yes
Why the entry is added or changed; kept on the entry for the approver. Up to 1000 characters.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
Changes the times, kind, job or note of an entry, with a reason kept on it. An APPROVED entry can only be changed by someone who approves timesheets (400 otherwise); any other change sends the entry back to OPEN for review. Same overlap rules as adding. Technicians: their own entries only (404 otherwise). Returns the entry.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
startedAt
string (date-time)
No
An instant as an ISO 8601 date-time with offset, e.g. 2026-10-05T08:30:00-05:00.
endedAt
string (date-time) or null
No
null keeps it running (only one per kind).
jobId
string or null
No
note
string or null
No
Up to 2000 characters.
reason
string
Yes
Why the entry is added or changed; kept on the entry for the approver. Up to 1000 characters.
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
startedAt
string (date-time)
endedAt
string (date-time) or null
note
string or null
source
enum
One of CLOCK, MANUAL, AUTO.
status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
One row per person with time in the week (and every linked technician): minutes per day and kind, paid minutes, the week's approval state and whether a clock is running. Technicians get only their own row. Read-only. Open a person with GET /timesheets/{userId}.
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.
GET /organizations/{organizationId}/timesheets/{userId}
A person's entries for the week with totals per day, for the week and per job, and the week's approval state. userId from GET /timesheets (or your own id from GET /users/me). Technicians: their own only (404 otherwise). Read-only.
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.
The week's state; null when empty. One of OPEN, SUBMITTED, APPROVED, REJECTED.
entries
array of object
entries[].id
string
entries[].organizationId
string
entries[].userId
string
entries[].technicianId
string or null
entries[].jobId
string or null
entries[].kind
enum
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
entries[].activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
entries[].startedAt
string (date-time)
entries[].endedAt
string (date-time) or null
entries[].note
string or null
entries[].source
enum
One of CLOCK, MANUAL, AUTO.
entries[].status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
entries[].editReason
string or null
entries[].editedByUserId
string or null
entries[].approvedByUserId
string or null
entries[].approvedAt
string (date-time) or null
entries[].createdAt
string (date-time)
entries[].updatedAt
string (date-time)
entries[].job
object or null
entries[].job.id
string
entries[].job.identifier
string
entries[].technician
object or null
entries[].technician.id
string
entries[].technician.name
string
entries[].technician.color
string
entries[].userName
string or null
entries[].minutes
integer
Whole minutes (a running entry counts to now).
entries[].date
string
The day it started, in the requested timezone.
days
array of object
days[].SHIFT
integer
days[].JOB
integer
days[].TRAVEL
integer
days[].BREAK
integer
days[].ACTIVITY
integer
days[].paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
days[].date
string
totals
object
totals.SHIFT
integer
totals.JOB
integer
totals.TRAVEL
integer
totals.BREAK
integer
totals.ACTIVITY
integer
totals.paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
POST /organizations/{organizationId}/timesheets/submit
Submits the caller's finished OPEN or REJECTED entries for the week for approval (SUBMITTED). Refused while a clock is running (409) or when there is nothing to submit (400). Emits timesheet.submitted. Returns the week.
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.
The week's state; null when empty. One of OPEN, SUBMITTED, APPROVED, REJECTED.
entries
array of object
entries[].id
string
entries[].organizationId
string
entries[].userId
string
entries[].technicianId
string or null
entries[].jobId
string or null
entries[].kind
enum
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
entries[].activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
entries[].startedAt
string (date-time)
entries[].endedAt
string (date-time) or null
entries[].note
string or null
entries[].source
enum
One of CLOCK, MANUAL, AUTO.
entries[].status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
entries[].editReason
string or null
entries[].editedByUserId
string or null
entries[].approvedByUserId
string or null
entries[].approvedAt
string (date-time) or null
entries[].createdAt
string (date-time)
entries[].updatedAt
string (date-time)
entries[].job
object or null
entries[].job.id
string
entries[].job.identifier
string
entries[].technician
object or null
entries[].technician.id
string
entries[].technician.name
string
entries[].technician.color
string
entries[].userName
string or null
entries[].minutes
integer
Whole minutes (a running entry counts to now).
entries[].date
string
The day it started, in the requested timezone.
days
array of object
days[].SHIFT
integer
days[].JOB
integer
days[].TRAVEL
integer
days[].BREAK
integer
days[].ACTIVITY
integer
days[].paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
days[].date
string
totals
object
totals.SHIFT
integer
totals.JOB
integer
totals.TRAVEL
integer
totals.BREAK
integer
totals.ACTIVITY
integer
totals.paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
POST /organizations/{organizationId}/timesheets/{userId}/review
decision: APPROVED approves every finished entry of the person's week (recording who and when); REJECTED sends them back to be fixed and resubmitted. Approved entries can then only be edited by approvers. Emits timesheet.approved / timesheet.rejected. Returns the week.
Permission
timesheets.approve (Owner, Admin)
Risk
write, OAuth scope servflo.write. Write: creates or changes records inside the business; nothing leaves it.
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.
The week's state; null when empty. One of OPEN, SUBMITTED, APPROVED, REJECTED.
entries
array of object
entries[].id
string
entries[].organizationId
string
entries[].userId
string
entries[].technicianId
string or null
entries[].jobId
string or null
entries[].kind
enum
SHIFT (clocked in), JOB (working a job), TRAVEL (on the way), BREAK, ACTIVITY (non-job work: see activity). One of SHIFT, JOB, TRAVEL, BREAK, ACTIVITY.
entries[].activity
enum or null
What an ACTIVITY entry was spent on. One of SHOP, SUPPLY_HOUSE, MEETING, TRAINING, VEHICLE, ADMIN, OTHER.
entries[].startedAt
string (date-time)
entries[].endedAt
string (date-time) or null
entries[].note
string or null
entries[].source
enum
One of CLOCK, MANUAL, AUTO.
entries[].status
enum
Approval state: OPEN, SUBMITTED, APPROVED or REJECTED. Running = endedAt null. One of OPEN, SUBMITTED, APPROVED, REJECTED.
entries[].editReason
string or null
entries[].editedByUserId
string or null
entries[].approvedByUserId
string or null
entries[].approvedAt
string (date-time) or null
entries[].createdAt
string (date-time)
entries[].updatedAt
string (date-time)
entries[].job
object or null
entries[].job.id
string
entries[].job.identifier
string
entries[].technician
object or null
entries[].technician.id
string
entries[].technician.name
string
entries[].technician.color
string
entries[].userName
string or null
entries[].minutes
integer
Whole minutes (a running entry counts to now).
entries[].date
string
The day it started, in the requested timezone.
days
array of object
days[].SHIFT
integer
days[].JOB
integer
days[].TRAVEL
integer
days[].BREAK
integer
days[].ACTIVITY
integer
days[].paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
days[].date
string
totals
object
totals.SHIFT
integer
totals.JOB
integer
totals.TRAVEL
integer
totals.BREAK
integer
totals.ACTIVITY
integer
totals.paid
integer
Paid minutes: SHIFT minus BREAK on a day with a shift, else JOB plus TRAVEL plus ACTIVITY.
GET /organizations/{organizationId}/timesheets/export
The week's entries as CSV (person, date, kind, start, end, decimal hours, job, status, source, note), for payroll. Optionally one person (userId). Technicians: their own only. Read-only.
IANA timezone days and weeks are counted in (e.g. America/Chicago). Defaults to the organization's timezone (Settings → General). Up to 100 characters.