Guides

Time

Export time entries and timesheets for payroll, record and correct hours, approve time, and read projects, tasks, clients and shift schedules through the API.

This guide covers time tracking in the API: time entries, timesheets, projects and schedules. Every parameter and field is in the API Reference.

Every endpoint in this guide needs time tracking switched on for the organization. While it is off they answer 403 MODULE_DISABLED, and no time events are sent by webhook.

Scopes for this area

TaskScopeLowest owner role
Read time entriestime_entries:readEmployee
Read clock-in and clock-out locationstime_entries.location:readAdministrator
Create, edit and delete time entriestime_entries:writeEmployee
Approve and reject time entriestime_entries:approveDepartment Head
Read timesheetstimesheets:readEmployee
Read timesheet pay figurestimesheets:read and users.employment:readAdministrator
Read projects, tasks and clientsprojects:readEmployee
Read shiftsschedules:readEmployee

The Time and payroll export template bundles the read scopes a payroll export needs.

Whose time a token can see

  • An Employee's token sees their own entries and timesheets.
  • A Department Head's token sees the people in the departments they head or manage.
  • Administrators and Executives see the whole organization.

An entry or timesheet the owner cannot see answers 404 NOT_FOUND. Filters such as user_id and department_id narrow that view and never widen it; department_id is for Administrator and Executive owners.

Money fields on a time entry (hourly_rate, billable_amount) appear on the owner's own entries, and on everyone's for Department Heads and above. Location fields (coordinates, addresses, accuracy, whether the clock-in was outside the geofence) need time_entries.location:read.

Export hours for a pay period

GET /time-entries reads a window of calendar days in the organization's timezone. The window defaults to the last 30 days and can be at most 120 days. Results are newest first.

curl "https://app.bookyourpto.com/api/v1/time-entries?start_date=2026-09-28&end_date=2026-10-11&approval_status=APPROVED&limit=100" \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN"
{
  "data": [
    {
      "id": "cmte00000000000000000001",
      "user_id": "cmusr0000000000000000012",
      "clock_in": "2026-10-08T16:00:00.000Z",
      "clock_out": "2026-10-09T00:30:00.000Z",
      "break_minutes": 30,
      "duration_minutes": 480,
      "project_id": "cmprj0000000000000000003",
      "task_id": "cmtsk0000000000000000007",
      "is_billable": true,
      "approval_status": "APPROVED",
      "source": "API",
      "...": "more fields"
    }
  ],
  "meta": { "request_id": "...", "has_more": false, "next_cursor": null }
}
  • clock_in and clock_out are instants in UTC. duration_minutes already has the break taken off.
  • Filter with user_id, department_id, project_id, approval_status and is_billable.
  • A window longer than 120 days, or an end_date before start_date, answers 422 VALIDATION_FAILED. For a longer period, request it in windows of up to 120 days.

If your organization runs period timesheets, GET /timesheets is usually the better source for payroll: one row per person per period with regular, overtime, holiday and paid-leave minutes, and the period's status (OPEN, SUBMITTED, APPROVED, FINALIZED, SIGNED or REJECTED). Filter with period_start, period_end, user_id and status. An OPEN timesheet carries its totals as last computed, so wait for FINALIZED before paying from it, or subscribe to timesheet.finalized.

Pay figures (regular_pay, overtime_pay, total_pay, currency) appear only when the token holds users.employment:read and its owner is an Administrator or Executive. They are never sent by webhook.

Reference: List time entries, List timesheets.

Record hours

curl -X POST https://app.bookyourpto.com/api/v1/time-entries \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -H "Idempotency-Key: 9b3e6f10-2c4a-4d8b-8e7f-1a5c3d9e2b64" \
  -d '{
    "clock_in": "2026-10-08T09:00:00-07:00",
    "clock_out": "2026-10-08T17:30:00-07:00",
    "break_minutes": 30,
    "project_id": "cmprj0000000000000000003",
    "task_id": "cmtsk0000000000000000007",
    "description": "Cycle count, aisles 4 to 9"
  }'
  • clock_in and clock_out are ISO 8601 date-times with a timezone offset. Entries made this way have source: "API".
  • Your organization must allow manual time entry; Administrators and Executives are exempt.
  • Only Administrator and Executive owners can create entries for someone else, with user_id.
  • Entries in a locked pay period are refused. Your organization's rounding rules apply.
  • An Administrator's or Executive's entry is approved at once. Otherwise the entry is PENDING when your organization requires approval, and a completed pending entry raises time_entry.submitted.

Reference: Create a time entry.

Correct or delete an entry

curl -X PATCH https://app.bookyourpto.com/api/v1/time-entries/cmte00000000000000000001 \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "clock_out": "2026-10-08T18:00:00-07:00", "description": "Cycle count, aisles 4 to 11" }'
  • Only the entry's owner, or an Administrator or Executive, can edit or delete it.
  • Clock times can be edited only when your organization allows it; Administrators and Executives are exempt.
  • When anyone other than an Administrator or Executive changes the hours, project, task, billing or rate of an APPROVED or REJECTED entry, it goes back to PENDING and time_entry.submitted is raised again.
  • Hours, rate and billing inside a finalized or signed timesheet cannot change: 409 CONFLICT.
  • hourly_rate can be set only by Administrator and Executive owners.
  • DELETE /time-entries/{id} marks the entry deleted and removes it from every list. It returns the entry as it now stands.

Reference: Update, Delete.

Approve or reject time

curl -X POST https://app.bookyourpto.com/api/v1/time-entries/cmte00000000000000000001/reject \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN" \
  -H "Content-Type: application/json" \
  -d '{ "reason": "Break not recorded; please add it and resubmit." }'
  • Needs time_entries:approve, and an owner who is an active Department Head, Administrator or Executive.
  • Nobody approves or rejects their own entries: 403 FORBIDDEN.
  • A Department Head decides only for people in their department scope.
  • A rejection reason is added to the entry's notes. The events are time_entry.approved and time_entry.rejected.

To build an approval queue, list GET /time-entries?approval_status=PENDING with the approver's token, or subscribe to time_entry.submitted.

Reference: Approve, Reject.

Projects, tasks and clients

curl "https://app.bookyourpto.com/api/v1/projects?status=ACTIVE" \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN"

curl "https://app.bookyourpto.com/api/v1/projects/cmprj0000000000000000003/tasks" \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN"
  • Administrators and Executives see every project; everyone else sees their department's projects plus organization-wide ones.
  • A project's hourly_rate and money budget appear only for Department Head, Administrator and Executive owners.
  • GET /projects/{id}/tasks returns every task of the project as a flat list; subtasks carry parent_task_id.
  • GET /clients is for Department Heads and above. An Employee's token gets 403 FORBIDDEN, even with projects:read.

Reference: Projects.

Shift schedules

curl "https://app.bookyourpto.com/api/v1/shifts?start_date=2026-10-12&end_date=2026-10-25" \
  -H "Authorization: Bearer $BOOKYOURPTO_TOKEN"

The window defaults to the next 7 days, starting today, and can be at most 120 days. Results are earliest first. Which shifts a token sees follows your organization's schedule visibility settings:

  • Administrators and Executives see every shift; Department Heads see their department scope.
  • Employees see their own shifts, or their department's or everyone's when your organization allows it, plus open shifts in their department.
  • Employees do not see weeks that have not been published, unless your organization uses default schedules.

Reference: List shifts.

Gotchas

  • Clocking in and out is not available through the API. Location and geofence checks belong to the device. Use POST /time-entries to record hours after the fact.
  • Windows are calendar days in the organization's timezone, not UTC. Read timezone from GET /organization when you build the dates.
  • Send offsets with times. A clock_in or clock_out without a timezone offset, such as -07:00 or Z, is refused with 422 VALIDATION_FAILED.
  • An edit can send an entry back for approval. Expect approval_status to change after a PATCH by a non-administrator.
  • Every page of a time-entry list is recorded as an export in the audit log.