Time Tracking integrations
This guide is for partners connecting an external time & attendance system (physical clocks, biometric terminals, mobile clock-in apps, workforce management platforms) with Factorial's Time Tracking module.
The goal is to push clock-in / clock-out events into Factorial in near real time, so that Factorial can act as the single source of truth for worked time, overtime, and payroll pre-processing.
Authentication
Factorial supports OAuth 2 and API Keys authentication methods.
Recommendation is using an OAuth 2.0 company token with time_tracking OAuth Scope
OAuth 2.0 with a company token is mandatory for partner integrations.
Employee identification
Factorial's API identifies employees by their internal employee_id. You must maintain a mapping between your device. These are a few options
company_identifier. A customer-controlled field on the employee (badge number, HR code, personnel number). Fetch employees viaGET /employees/employeesand match on it.- A custom field that can be retrieved by CustomFields > Value
You can cache the mapping locally and refresh it periodically, or subscribe to employees/employee/* webhooks to keep it fresh.
Time format
- All timestamps: ISO-8601 with timezone offset (e.g.
2024-06-23T11:00:00+02:00). - Dates:
YYYY-MM-DD. - Always send the offset the employee was in when the event happened
Integration flow
There are two possible topologies. You can pick the one that better matches your case.
A) Real-time streaming (physical clocks, terminals, mobile apps)
- Employee taps / scans on your device.
- Resolve device id → Factorial
employee_idfrom your cached mapping. - Call Attendance > Shift > Toggle clocks with
employee_idand the ISO-8601 timestamp. Factorial figures out whether it's an entry or an exit based on the employee's current shift state. - Store the returned
id. - On failure, retry with idempotency: Attendance > Shift to check whether the shift already exists before retrying.
Alternatives when your device semantically distinguishes events:
- POST Clocks in a shift or Clocks out a shift
- POST Break ends a Shift or Break ends a Shift for breaks inside an open shift.
B) Batch sync (end-of-day upload from a workforce management system)
- Collect completed shifts for the period.
- For each shift, call
POST /attendance/shiftswith the full shift (employee, date, clock-in, clock-out). - Store the returned
id. - On a schedule,
GET /attendance/shifts?updated_at=...to pull manual corrections done in Factorial back into your system.
Two-way sync
Subscribe to attendance/shift/* webhooks (clock_in, clock_out, create, update, delete) to reflect manual edits made in Factorial back to your system. See Webhooks reference.
Best practices
- Always include timezone offsets in timestamps — the #1 source of bugs.
- Respect the open-shift model. A
clock_inopens a shift until a matchingclock_out. Don't send two consecutiveclock_inevents for the same employee. - Use breaks endpoints rather than closing and reopening shifts.
- Idempotency. The API does not deduplicate — check existing shifts before retrying.
- API versioning. Endpoints are versioned (
/api/YYYY-MM-DD/...). Monitor the changelog.
We're excited to see the integration you build! 🚀

