Zum Inhalt springen
Esc
↑↓navigieren↵öffnen⌘Jvorschau
Auf dieser Seite

Fuxam API v4

Time-tracking sessions, logs, and timestamp templates.

Version 4.3.0
Base URLhttps://fuxam.app/api/v4https://dev.fuxam.app/api/v4

Time tracking

Institution Zeiterfassung for partner terminals (ananas.codes / Datafox) and HR integrations. Auth: HTTP Basic (clientId:clientSecret). Feature gate: 403 when time tracking is disabled for the institution.

Identify a member with exactly one of userId, email, or membership code (badge). Sending none or more than one is 400. Whitespace-only code (for example " ") is 422. An unknown code is 404. This is punch identity only — there is no user provisioning on this API.

Numeric keypad codes (Datafox and similar): store the membership code in Fuxam with a fixed prefix, for example Datafox-1234. The terminal adds Datafox- when it sends code and strips that prefix when it displays the number. Lookup is the stored code after trim (the column collation is case-insensitive). This API does not add or strip a prefix.

The institution setting user_code_format (Dashboard → Settings → User management, /{lang}/dashboard/settings/user-management) can require that whole-code shape on writes. It is literal text plus at least four bracket tokens ([0] is one digit). Datafox-[0][0][0][0] matches Datafox-1234. Literals are case-sensitive. A prefix alone is not a valid format: Datafox- is rejected (NO_DYNAMIC_TOKEN) and Datafox-[0] is rejected (MIN_BLOCKS_NOT_MET, fewer than four tokens). The format describes the entire code, not “prefix plus anything”. Time-tracking reads do not re-check the format.

Typical punch sequence:

  1. GET /time-tracking/timestamp-templates — optional; cache category IDs
  2. POST /time-tracking/sessions/start — clock in
  3. Optional POST /time-tracking/sessions/pause then POST /time-tracking/sessions/resume
  4. Optional POST /time-tracking/timestamps — category on today’s session (templateId and/or label)
  5. POST /time-tracking/sessions/stop — clock out

Offline catch-up: the supported way to replay an offline day is POST /time-tracking/logs/bulk with complete startTime + endTime pairs (optional pauses). POST /time-tracking/sessions/start and stop with at are for near-real-time punches. An open session that started on an earlier institution-local day than the punch is auto-closed at the end of that start day (23:59:59.999 in the institution timezone). Do not rebuild a past day with start/stop. Edit a stored log with PATCH /time-tracking/logs/{id}.

Already running: if any open session conflicts with the punch, POST /time-tracking/sessions/start returns 409 and writes nothing. Conflict means the open session started on the punch’s local day or later. The body includes activeSession.id and activeSession.startTime. Stop that session, then retry. Start also returns 409 conflictingLog when the open interval [punch, ∞) overlaps another log (the same half-open rule as POST /time-tracking/logs). Stop returns 409 conflictingLog when [sessionStart, stop) overlaps another log; the session being stopped is excluded, and a stop that only touches the next log startTime is accepted. For conflictingLog, adjust or delete the existing log via the UI or PATCH, or resend non-overlapping times. Every non-conflicting leftover from an earlier local day is closed at its own end-of-day before the new session is created. closedActiveSession in the 201 body is the earliest of those closes (the web UI still closes only one findFirst session and can auto-close a same-day session).

Idempotency: a completed success is replayed when the same Idempotency-Key and body are sent again. A 409 or 503 does not store a response; the key is released. After 409, stop the open session and retry start with the same key. After 503, retry the same request.

Overlap: POST /time-tracking/logs and each item of POST /time-tracking/logs/bulk reject an interval that overlaps an existing log or open session for that member (409, conflictingLog with id, startTime, and endTime). Intervals are half-open [start, end) on absolute instants, so ending exactly when the next log starts — including a local midnight boundary — is not an overlap. An open session (endTime null) occupies [start, ∞) and conflicts with any interval that ends after that start, including later days. Close it before importing those days. Bulk rejection is per item, same as other v4 batches: HTTP 200, failed items are listed, earlier items in the request stay created, and a later item that overlaps an earlier one in the same batch fails with that item as conflictingLog. PATCH /time-tracking/logs/{id} uses the same half-open overlap check, excludes the log being edited, and returns 409 conflictingLog. The Fuxam UI editor does not.

Timezone: day boundaries and auto-close use time_tracking_timezone (Dashboard → Settings → Time tracking, /{lang}/dashboard/settings/time-tracking). Set it, for example Europe/Berlin. When it is unset, these API routes do not pass a timezone and a terminal request has no browser timezone cookie, so resolution falls through to UTC. An auto-close at 23:59:59.999 UTC then displays as 01:59 in Berlin during CEST (UTC+2). That fallback is unchanged.

Delete: not supported on this API. Admins delete logs in the Fuxam UI.

Mutating session punches and log creates require Idempotency-Key. Optional at is ISO-8601 with timezone offset for near-real-time punches; omit it to use server now. GET /time-tracking/sessions/active returns { "data": null } when the member is not clocked in. List logs is per member (not institution-wide).

War diese Seite hilfreich?