REST API reference
ClockShark API
15 endpoints for ClockShark. Each one is a POST with a JSON body, called with your API key.
- Base URL
- https://cotlet.dev/api/v1/clockshark
- Connects with
- Your ClockShark admin or manager account
- Integration page
- ClockShark
| Endpoint | Access | Description |
|---|---|---|
| list_time_entries | read | Shifts from Time > View: employee, job, task, start, end, breaks, notes, alerts and approval status. |
| list_clocked_in | read | Employees on an active shift now, with job, task and the GPS location of their last punch. |
| list_shifts | read | Scheduled shifts, published and draft, with employee, job, task, times and notes. |
| list_jobs | read | Jobs from Work > Jobs with number, stage, customer and address. |
| get_job | read | Job details: description, address, customer, stage, labor budget, comments and attachment list. |
| list_time_off_requests | read | Requests from Time > Requests with employee, policy, dates, hours and status. Pro plan. |
| export_time_csv | read | The CSV Export report: paid, regular, overtime and double time minutes per shift, as a download link. |
| add_time_entry | write | Manually add a shift to an employee timesheet, the way a manager does on the web. |
| edit_time_entry | write | Change start, end, job, task or notes of an unapproved shift. Saved to the audit log. |
| approve_timesheets | write | Approve, or unapprove, employee timesheets for a day, week or pay period. Needs timesheet approvals turned on. |
| create_job | write | New job employees can clock into, with customer, address and description. |
| create_shift | write | Schedule one or more employees on a job, saved as a draft until you publish it. |
| publish_shifts | write | Publish draft shifts so they appear in employees' mobile app. |
| respond_time_off_request | write | Approve or decline a request. ClockShark emails the employee; a decline cannot be undone. |
| add_job_comment | write | Comment on a job thread; @mentioned users get a notification. |
List time entries
readPOST https://cotlet.dev/api/v1/clockshark/list_time_entries
Returns shifts for a date range, oldest first, with the alerts ClockShark raised on each, such as a missing clock out. Filter by employee, by approval status or to shifts with alerts only. Use entry_id and employee_id from here in the edit and approve tools.
Parameters
| Name | Type | Description |
|---|---|---|
| from required | date | First day of the range. |
| to required | date | Last day of the range. |
| employee_ids | string[] | Only these employees. Default: everyone you manage. |
| approval_status | enum | all, approved or unapproved. Default: all. |
| with_alerts_only | boolean | Only shifts with timesheet alerts, such as a missing clock out. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/list_time_entries \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-01","to":"2026-10-01"}' result = client.call("clockshark", "list_time_entries", {"from":"2026-10-01","to":"2026-10-01"}) const result = await cotlet.call('clockshark', 'list_time_entries', {"from":"2026-10-01","to":"2026-10-01"}); cotlet call clockshark list_time_entries --data '{"from":"2026-10-01","to":"2026-10-01"}' Example response
{
"entries": [
{
"entry_id": "te_90412",
"employee_id": "e_48213",
"employee": "Mike Torres",
"job": "42 Oak Street",
"task": "Framing",
"start": "2026-10-09T07:00:00-05:00",
"end": null,
"break_minutes": 30,
"alerts": [
"Missing clock out"
],
"approved": false
},
{
"entry_id": "te_90420",
"employee_id": "e_48219",
"employee": "Luis Ortega",
"job": "42 Oak Street",
"task": "Framing",
"start": "2026-10-09T07:02:00-05:00",
"end": "2026-10-09T15:31:00-05:00",
"break_minutes": 30,
"alerts": [],
"approved": false
}
]
} POST https://cotlet.dev/api/v1/clockshark/list_clocked_in
Returns employees with an open shift at the moment of the call. Each item has the job, the task, the clock in time and the location of the last punch. An employee with no open shift is not listed.
Parameters
No parameters.
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/list_clocked_in \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("clockshark", "list_clocked_in") const result = await cotlet.call('clockshark', 'list_clocked_in'); cotlet call clockshark list_clocked_in Example response
{
"clocked_in": [
{
"employee_id": "e_48219",
"employee": "Luis Ortega",
"job": "42 Oak Street",
"task": "Framing",
"since": "2026-10-11T07:02:00-05:00",
"last_punch": {
"lat": 41.8781,
"lng": -87.6298
}
}
]
} List shifts
readPOST https://cotlet.dev/api/v1/clockshark/list_shifts
Returns scheduled shifts for a date range, earliest first. Status shows whether crews can already see a shift in the mobile app (published) or not yet (draft). Use shift_id with publish_shifts.
Parameters
| Name | Type | Description |
|---|---|---|
| from required | date | First day of the range. |
| to required | date | Last day of the range. |
| employee_ids | string[] | Only these employees. Default: everyone you manage. |
| status | enum | all, published or draft. Default: all. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/list_shifts \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-01","to":"2026-10-01"}' result = client.call("clockshark", "list_shifts", {"from":"2026-10-01","to":"2026-10-01"}) const result = await cotlet.call('clockshark', 'list_shifts', {"from":"2026-10-01","to":"2026-10-01"}); cotlet call clockshark list_shifts --data '{"from":"2026-10-01","to":"2026-10-01"}' Example response
{
"shifts": [
{
"shift_id": "s_77120",
"employee_id": "e_48213",
"job_id": "j_3307",
"start": "2026-10-12T07:00:00-05:00",
"end": "2026-10-12T15:30:00-05:00",
"status": "published",
"notes": ""
}
]
} List jobs
readPOST https://cotlet.dev/api/v1/clockshark/list_jobs
Returns jobs your account can see. By default only active jobs are listed. Use job_id from here in time, schedule and comment tools.
Parameters
| Name | Type | Description |
|---|---|---|
| active | boolean | Only active jobs. Default: true. |
| customer | string | Only jobs of this customer. |
| search | string | Match on job name or number. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/list_jobs \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("clockshark", "list_jobs") const result = await cotlet.call('clockshark', 'list_jobs'); cotlet call clockshark list_jobs Example response
{
"jobs": [
{
"job_id": "j_3307",
"number": "2041",
"name": "42 Oak Street",
"stage": "Active",
"customer": "Harlow Homes",
"address": "42 Oak Street, Springfield"
}
]
} Get job
readPOST https://cotlet.dev/api/v1/clockshark/get_job
Returns one job with its labor budget, the comment thread and the names of attached files. Attachments are listed, not downloaded.
Parameters
| Name | Type | Description |
|---|---|---|
| job_id required | string | Job ID from list_jobs. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/get_job \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id":"job_8c41d2"}' result = client.call("clockshark", "get_job", {"job_id":"job_8c41d2"}) const result = await cotlet.call('clockshark', 'get_job', {"job_id":"job_8c41d2"}); cotlet call clockshark get_job --data '{"job_id":"job_8c41d2"}' Example response
{
"job_id": "j_3307",
"number": "2041",
"name": "42 Oak Street",
"stage": "Active",
"customer": "Harlow Homes",
"address": "42 Oak Street, Springfield",
"description": "Wall framing, level 1.",
"budget_hours": 320,
"comments": [
{
"author": "Dana Reed",
"body": "Lumber arrives Monday 6:30.",
"created_at": "2026-10-08T16:10:00-05:00"
}
],
"attachments": [
"floor-plan.pdf"
]
} POST https://cotlet.dev/api/v1/clockshark/list_time_off_requests
Returns time off requests, pending ones by default, newest first. Each has the policy, the dates and the hours requested. Time off requests are a Pro plan feature, so the call fails on other plans.
Parameters
| Name | Type | Description |
|---|---|---|
| status | enum | pending, approved, declined or all. Default: pending. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/list_time_off_requests \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("clockshark", "list_time_off_requests") const result = await cotlet.call('clockshark', 'list_time_off_requests'); cotlet call clockshark list_time_off_requests Example response
{
"requests": [
{
"request_id": "r_20871",
"employee_id": "e_48219",
"employee": "Luis Ortega",
"policy": "Vacation",
"from": "2026-10-19",
"to": "2026-10-20",
"hours": 16,
"status": "pending"
}
]
} Export time CSV
readPOST https://cotlet.dev/api/v1/clockshark/export_time_csv
Returns a download link to the CSV Export report for the range, plus the row count and totals in minutes, so your agent can answer without opening the file. Notes are left out unless include_notes is true. It reads the report and changes nothing.
Parameters
| Name | Type | Description |
|---|---|---|
| from required | date | First day of the range. |
| to required | date | Last day of the range. |
| employee_ids | string[] | Only these employees. Default: everyone you manage. |
| include_notes | boolean | Add timesheet notes. Default: false. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/export_time_csv \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"from":"2026-10-01","to":"2026-10-01"}' result = client.call("clockshark", "export_time_csv", {"from":"2026-10-01","to":"2026-10-01"}) const result = await cotlet.call('clockshark', 'export_time_csv', {"from":"2026-10-01","to":"2026-10-01"}); cotlet call clockshark export_time_csv --data '{"from":"2026-10-01","to":"2026-10-01"}' Example response
{
"download_url": "https://app.clockshark.com/exports/csv/2026-10-05_2026-10-11.csv",
"rows": 3,
"totals": {
"paid_minutes": 1530,
"regular_minutes": 1440,
"overtime_minutes": 90,
"double_time_minutes": 0
}
} Add time entry
writePOST https://cotlet.dev/api/v1/clockshark/add_time_entry
Adds a shift for one employee against a job and a task, with start and end as ISO 8601 times with a time zone. It reaches no one and a wrong entry is fixed with edit_time_entry, so it runs without asking. The new entry is unapproved.
Parameters
| Name | Type | Description |
|---|---|---|
| employee_id required | string | Employee ID from list_time_entries. |
| job_id required | string | Job ID from list_jobs. |
| task_id required | string | Task to log the time against. |
| start required | datetime | ISO 8601 with time zone. |
| end required | datetime | ISO 8601 with time zone. |
| notes | string | Timesheet note. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/add_time_entry \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"employee_id":"employee_8c41d2","job_id":"job_8c41d2","task_id":"task_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"}' result = client.call("clockshark", "add_time_entry", {"employee_id":"employee_8c41d2","job_id":"job_8c41d2","task_id":"task_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"}) const result = await cotlet.call('clockshark', 'add_time_entry', {"employee_id":"employee_8c41d2","job_id":"job_8c41d2","task_id":"task_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"}); cotlet call clockshark add_time_entry --data '{"employee_id":"employee_8c41d2","job_id":"job_8c41d2","task_id":"task_8c41d2","start":"2026-10-01T09:00:00Z","end":"2026-10-01T09:00:00Z"}' Example response
{
"entry_id": "te_90433",
"employee_id": "e_48213",
"job_id": "j_3307",
"start": "2026-10-09T07:00:00-05:00",
"end": "2026-10-09T15:30:00-05:00",
"approved": false
} Edit time entry
writePOST https://cotlet.dev/api/v1/clockshark/edit_time_entry
Changes the fields you pass and leaves the rest. It works on unapproved shifts only, so unapprove the timesheet first if needed. Each edit is saved to the audit log. It reaches no one and is undone by editing again, so it runs without asking.
Parameters
| Name | Type | Description |
|---|---|---|
| entry_id required | string | Entry ID from list_time_entries. |
| fields required | object | Any of start, end, job_id, task_id, notes. |
| ignore_alerts | boolean | Mark the shift alerts as ignored. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/edit_time_entry \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"entry_id":"te_90412","fields":{"end":"2026-10-09T16:30:00-05:00","notes":"End set to schedule, confirmed by text"},"ignore_alerts":true}' result = client.call("clockshark", "edit_time_entry", {"entry_id":"te_90412","fields":{"end":"2026-10-09T16:30:00-05:00","notes":"End set to schedule, confirmed by text"},"ignore_alerts":True}) const result = await cotlet.call('clockshark', 'edit_time_entry', {"entry_id":"te_90412","fields":{"end":"2026-10-09T16:30:00-05:00","notes":"End set to schedule, confirmed by text"},"ignore_alerts":true}); cotlet call clockshark edit_time_entry --data '{"entry_id":"te_90412","fields":{"end":"2026-10-09T16:30:00-05:00","notes":"End set to schedule, confirmed by text"},"ignore_alerts":true}' Example response
{
"entry_id": "te_90412",
"start": "2026-10-09T07:00:00-05:00",
"end": "2026-10-09T16:30:00-05:00",
"alerts": [],
"approved": false
} Approve timesheets
writePOST https://cotlet.dev/api/v1/clockshark/approve_timesheets
Approves every shift of the listed employees in the range and returns paid and overtime hours per employee. Timesheet approvals must be turned on in your account. It reaches no one and action unapprove reverses it, so it runs without asking.
Parameters
| Name | Type | Description |
|---|---|---|
| employee_ids required | string[] | Employees whose timesheets to approve. |
| from required | date | First day of the range. |
| to required | date | Last day of the range. |
| action | enum | approve or unapprove. Default: approve. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/approve_timesheets \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"employee_ids":["e_48213","e_48219"],"from":"2026-10-05","to":"2026-10-11","action":"approve"}' result = client.call("clockshark", "approve_timesheets", {"employee_ids":["e_48213","e_48219"],"from":"2026-10-05","to":"2026-10-11","action":"approve"}) const result = await cotlet.call('clockshark', 'approve_timesheets', {"employee_ids":["e_48213","e_48219"],"from":"2026-10-05","to":"2026-10-11","action":"approve"}); cotlet call clockshark approve_timesheets --data '{"employee_ids":["e_48213","e_48219"],"from":"2026-10-05","to":"2026-10-11","action":"approve"}' Example response
{
"approved": 2,
"period": {
"from": "2026-10-05",
"to": "2026-10-11"
},
"timesheets": [
{
"employee_id": "e_48213",
"paid_hours": 41.5,
"overtime_hours": 1.5,
"status": "approved"
},
{
"employee_id": "e_48219",
"paid_hours": 38,
"overtime_hours": 0,
"status": "approved"
}
]
} Create job
writePOST https://cotlet.dev/api/v1/clockshark/create_job
Creates a job with an optional number, customer, address and description, and a labor budget in hours. The description shows to field employees in the mobile app. It reaches no one by itself and runs without asking.
Parameters
| Name | Type | Description |
|---|---|---|
| name required | string | Job name. |
| number | string | Job number. |
| customer | string | Existing customer name or ID. |
| address | string | Job site address. |
| description | string | Shown to field employees in the mobile app. |
| budget_hours | integer | Total hours budgeted for the labor budget. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/create_job \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"name":"Jane Doe"}' result = client.call("clockshark", "create_job", {"name":"Jane Doe"}) const result = await cotlet.call('clockshark', 'create_job', {"name":"Jane Doe"}); cotlet call clockshark create_job --data '{"name":"Jane Doe"}' Example response
{
"job_id": "j_3307",
"number": "2041",
"name": "42 Oak Street",
"stage": "Active",
"budget_hours": 320
} Create shift
writePOST https://cotlet.dev/api/v1/clockshark/create_shift
Creates one shift per employee on a job with start and end as ISO 8601 times. Shifts are saved as drafts, so crews see nothing until publish_shifts. It runs without asking for that reason.
Parameters
| Name | Type | Description |
|---|---|---|
| employee_ids required | string[] | Employees to schedule. |
| job_id required | string | Job ID from list_jobs. |
| start required | datetime | ISO 8601 with time zone. |
| end required | datetime | ISO 8601 with time zone. |
| task_id | string | Task for the shift. |
| notes | string | Shift notes for the crew. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/create_shift \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"employee_ids":["e_48213","e_48219"],"job_id":"j_3307","start":"2026-10-13T07:00:00-05:00","end":"2026-10-13T15:30:00-05:00"}' result = client.call("clockshark", "create_shift", {"employee_ids":["e_48213","e_48219"],"job_id":"j_3307","start":"2026-10-13T07:00:00-05:00","end":"2026-10-13T15:30:00-05:00"}) const result = await cotlet.call('clockshark', 'create_shift', {"employee_ids":["e_48213","e_48219"],"job_id":"j_3307","start":"2026-10-13T07:00:00-05:00","end":"2026-10-13T15:30:00-05:00"}); cotlet call clockshark create_shift --data '{"employee_ids":["e_48213","e_48219"],"job_id":"j_3307","start":"2026-10-13T07:00:00-05:00","end":"2026-10-13T15:30:00-05:00"}' Example response
{
"shifts": [
{
"shift_id": "s_77201",
"employee_id": "e_48213",
"job_id": "j_3307",
"start": "2026-10-12T07:00:00-05:00",
"end": "2026-10-12T15:30:00-05:00",
"status": "draft"
},
{
"shift_id": "s_77202",
"employee_id": "e_48219",
"job_id": "j_3307",
"start": "2026-10-12T07:00:00-05:00",
"end": "2026-10-12T15:30:00-05:00",
"status": "draft"
}
]
} POST https://cotlet.dev/api/v1/clockshark/publish_shifts
Publishes the shifts you name, or all drafts in a date range, and returns how many went out. Employees see published shifts in their mobile app. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| shift_ids | string[] | Shifts to publish. Default: all drafts in the range. |
| from | date | First day of the range. |
| to | date | Last day of the range. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/publish_shifts \
-H "Authorization: Bearer $COTLET_API_KEY" result = client.call("clockshark", "publish_shifts") const result = await cotlet.call('clockshark', 'publish_shifts'); cotlet call clockshark publish_shifts Example response
{
"published": 2,
"shift_ids": [
"s_77201",
"s_77202"
]
} POST https://cotlet.dev/api/v1/clockshark/respond_time_off_request
Approves or declines one pending request. ClockShark emails the employee, and a note is shown with a decline. A decline cannot be undone. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| request_id required | string | Request ID from list_time_off_requests. |
| decision required | enum | approve or decline. |
| note | string | Reason, shown with a decline. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/respond_time_off_request \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"request_id":"r_20871","decision":"approve"}' result = client.call("clockshark", "respond_time_off_request", {"request_id":"r_20871","decision":"approve"}) const result = await cotlet.call('clockshark', 'respond_time_off_request', {"request_id":"r_20871","decision":"approve"}); cotlet call clockshark respond_time_off_request --data '{"request_id":"r_20871","decision":"approve"}' Example response
{
"request_id": "r_20871",
"employee": "Luis Ortega",
"decision": "approve",
"status": "approved"
} POST https://cotlet.dev/api/v1/clockshark/add_job_comment
Posts a comment on the job thread under your name. Users you @mention get a notification. By default you confirm each call; you can switch that off for this tool.
Parameters
| Name | Type | Description |
|---|---|---|
| job_id required | string | Job ID from list_jobs. |
| body required | string | Comment text. Mention users as @Name. |
Request
curl -X POST https://cotlet.dev/api/v1/clockshark/add_job_comment \
-H "Authorization: Bearer $COTLET_API_KEY" \
-H "Content-Type: application/json" \
-d '{"job_id":"job_8c41d2","body":"body"}' result = client.call("clockshark", "add_job_comment", {"job_id":"job_8c41d2","body":"body"}) const result = await cotlet.call('clockshark', 'add_job_comment', {"job_id":"job_8c41d2","body":"body"}); cotlet call clockshark add_job_comment --data '{"job_id":"job_8c41d2","body":"body"}' Example response
{
"comment_id": "c_5521",
"job_id": "j_3307",
"body": "@Dana Reed lumber is confirmed for Monday 6:30.",
"created_at": "2026-10-09T16:12:00-05:00"
}