---
title: "2.0 Architecture"
space: "ZKTeco Biometric Integration for FrappeHR"
url: "https://docs.navari.co.ke/zkteco/architecture-and-how-it-works"
updated: "2026-05-24"
---

The integration operates as a server-side Frappe scheduled job. There is no external daemon or middleware required everything runs within the bench process.

### Authentication Flow

1. On save of the `ZKTeco Biometric Settings` document, the system calls the ZKTeco device REST API with the configured admin credentials.
2. The device returns a JWT token, which the system stores against the settings record.
3. All subsequent API calls (data fetch, user enable/disable) attach this token in the `Authorization` header.
4. The system monitors token expiry and performs renewal automatically before making a new request.

### Data Synchronization Flow

```
Frappe Scheduler
      |
      v
Scheduled Job fires (per configured frequency)
      |
      v
Fetch punch transactions from ZKTeco device API
      |
      v
For each transaction:
  - Resolve emp_code → Employee (via Biometric ID field)
  - Check for existing Employee Check-in with same employee + timestamp
  - If no duplicate: create Employee Check-in record (IN or OUT)
      |
      v
Update last_sync_timestamp on settings document
      |
      v
Write sync result to Frappe logs

```

### User Status Control Flow

After each Employee Check-in record is created, the system calls the ZKTeco device API to update the biometric user's access state:

- **OUT punch** -> disable user account on device (biometric data retained, access blocked)
- **IN punch** -> re-enable user account on device (full biometric access restored)

This means the device itself enforces access restrictions based on attendance state in FrappeHR, not just as a reporting mechanism.