Clock in / clock out
Securely start or stop an employee punch from an approved partner integration.
Explicitly clock an employee in (start) or out (stop) from a trusted server-side integration.
POST https://pro.curiotime.com/api/v1/companies/{companyId}/punches
Authorization: Bearer {token}
Content-Type: application/json
Roles: owner, manager
The companyId in the route must match the company in the JWT. This endpoint does not accept or require an employee
password or PIN.
Clock in
{
"employeeId": "b8cbbc53-b2a6-43ea-8825-51e6aac0171e",
"action": "start",
"projectId": null,
"subProjectId": null,
"latitude": 64.1466,
"longitude": -21.9426
}
Clock out
Use the same URL and employee identifier with action set to stop:
{
"employeeId": "b8cbbc53-b2a6-43ea-8825-51e6aac0171e",
"action": "stop",
"latitude": 64.1466,
"longitude": -21.9426
}
projectId and subProjectId are only used when clocking in.
Request fields
| Field | Required | Description |
|---|---|---|
employeeId |
Yes | Employee GUID in the company |
action |
Yes | start to clock in or stop to clock out |
projectId |
No | Project GUID for clock-in; omit for clock-out |
subProjectId |
No | Subproject GUID; requires projectId |
latitude, longitude |
No | Supply both or neither. Latitude: -90…90; longitude: -180…180 |
Response
{
"success": true,
"data": {
"message": "Clocked in.",
"isClockedIn": true,
"timeEntryId": "f984ec1b-8dbb-40c3-a27c-12dcadce3c83",
"punchedAtUtc": "2026-09-30T10:00:00Z",
"punchPhotoUploadGrant": null,
"punchPhotoUploadGrantExpiresAtUtc": null
},
"errors": null
}
Errors and retrying
| Status | Meaning |
|---|---|
400 |
Invalid request, coordinates or action |
401 |
Missing, expired or invalid Bearer token |
403 |
Role is not allowed, or token company does not match the route |
404 |
Employee, project or related resource was not found |
409 |
State conflict, such as starting an already-open punch |
429 |
More than 120 punch requests per minute for the authenticated subject |
Do not blindly retry 400, 403, 404 or 409. On 429, retry with exponential backoff. Use the returned
timeEntryId as the system record identifier.
If the connection times out after sending a punch, read the employee’s time entries to confirm whether the state changed before retrying. The endpoint does not currently accept an idempotency key.
Related
- Authentication
- Time entries — verify worked time and calculated totals
- OpenAPI — machine-readable schema