🔐 ZKTeco Device API

Complete Flow Documentation & Integration Guide

Version 1.0.1 | RESTful API for fingerprint device management and access control

📖 API Overview

ZKTeco Device API menyediakan interface RESTful untuk mengelola fingerprint devices, user management, attendance tracking, dan door access control.

🔑 Key Features:

  • JWT-based authentication dengan access & refresh tokens
  • Real-time device communication dengan ZKTeco fingerprint readers
  • Async job processing menggunakan queue system
  • Caching untuk optimasi performance
  • Comprehensive attendance & user management

📊 API Statistics

Category Endpoints Description
JWT Auth Users 2 Authentication & user registration
Attendance 5 Attendance records management
Device Management 3 Device CRUD operations
Device Operations 3 Device control (restart, info, etc)
Door Control 1 Door unlock operations
User Management 6 User sync & management on devices
Queue & Cache 2 Background jobs & cache management

🏗️ System Architecture

High-Level Architecture

graph TB Client[Client Application] API[CI 4 API Server
Python exe] Auth[Auth Service
JWT] Queue[Queue System
Bull/Redis] Cache[Redis Cache] DB[(MySQL
Database)] Device[ZKTeco Device
Fingerprint Reader] Client -->|HTTP/REST| API API --> Auth API --> Queue API --> Cache API --> DB Queue -->|Background Jobs| Device API -->|Direct Communication| Device Device -->|Attendance Data| API style Client fill:#e1f5ff style API fill:#dbeafe style Auth fill:#fef3c7 style Queue fill:#d1fae5 style Cache fill:#fee2e2 style DB fill:#e0e7ff style Device fill:#fce7f3

Request Flow Architecture

sequenceDiagram participant C as Client participant G as API Gateway participant A as Auth Middleware participant Ctrl as Controller participant Svc as Service Layer participant Q as Queue participant Cache as Redis Cache participant DB as Database participant Dev as ZKTeco Device C->>G: HTTP Request G->>A: Verify JWT Token alt Valid Token A->>Ctrl: Authenticated Request Ctrl->>Svc: Business Logic alt Check Cache Svc->>Cache: Get Cached Data Cache-->>Svc: Return if exists end alt Direct Operation Svc->>Dev: TCP Connection Dev-->>Svc: Device Response end alt Async Operation Svc->>Q: Add Job to Queue Q-->>Svc: Job Queued Note over Q,Dev: Background Processing Q->>Dev: Process Job Dev-->>Q: Result Q->>DB: Save Result end Svc->>DB: Persist Data DB-->>Svc: Success Svc-->>Ctrl: Result Ctrl-->>G: Format Response G-->>C: JSON Response else Invalid Token A-->>G: 401 Unauthorized G-->>C: Error Response end

🔐 Authentication Flow

POST /api/v1/auth/login JWT Auth Users

Summary: Authenticate user and get JWT tokens

🔄 Login Flow Diagram

sequenceDiagram participant Client participant API participant AuthService participant Database participant JWT Client->>API: POST /api/v1/auth/login Note over Client,API: {email, password} API->>AuthService: authenticate(credentials) AuthService->>Database: SELECT user WHERE email alt User Found Database-->>AuthService: User data AuthService->>AuthService: bcrypt.compare(password) alt Password Valid AuthService->>JWT: generateAccessToken(user) JWT-->>AuthService: access_token (1h) AuthService->>JWT: generateRefreshToken(user) JWT-->>AuthService: refresh_token (7d) AuthService-->>API: tokens + user data API-->>Client: 200 OK + tokens else Password Invalid AuthService-->>API: Invalid password API-->>Client: 401 Unauthorized end else User Not Found Database-->>AuthService: null AuthService-->>API: User not found API-->>Client: 401 Unauthorized end

Request Body

{
  "email": "[email protected]",
  "password": "danish123"
}

Success Response (200 OK)

{
  "status": true,
  "message": "Login successful",
  "data": {
    "access_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGciOiJIUzI1NiJ9...",
    "token_type": "Bearer",
    "expires_in": 3600
  }
}

Error Response (401 Unauthorized)

{
  "status": false,
  "message": "Invalid credentials",
  "error": {
    "code": "INVALID_CREDENTIALS",
    "details": "Email atau password salah"
  }
}

📋 Data Flow Table

Step Component Input Processing Output Status
1 Client email, password Send POST request - -
2 Validation Request body Validate email format Validated data 200 / 400
3 Database Email Find user by email User object Found / 404
4 Auth Service password + hash bcrypt.compare() Boolean Match / 401
5 JWT Service User data Generate tokens access + refresh tokens 200
6 Response Tokens Format response JSON response 200

🔒 Security Notes:

  • Password di-hash menggunakan bcrypt sebelum disimpan
  • Access token expires dalam 1 jam (3600 seconds)
  • Refresh token expires dalam 7 hari
  • Token disimpan di client (localStorage/cookies)
  • Gunakan HTTPS untuk semua API calls
POST /api/v1/auth/register JWT Auth Users Admin Only

Summary: Register new user (Admin only)

⚠️ Authorization Required:

Endpoint ini memerlukan authentication token dengan role "admin"

Header: Authorization: Bearer {admin_access_token}

🔄 Registration Flow Diagram

sequenceDiagram participant Admin participant API participant AuthMiddleware participant AuthService participant Database Admin->>API: POST /api/v1/auth/register Note over Admin,API: Authorization: Bearer token API->>AuthMiddleware: Verify JWT alt Valid Admin Token AuthMiddleware->>AuthMiddleware: Check role === 'admin' alt Is Admin AuthMiddleware->>AuthService: createUser(data) AuthService->>Database: Check email exists alt Email Available AuthService->>AuthService: bcrypt.hash(password) AuthService->>Database: INSERT user Database-->>AuthService: user_id AuthService-->>API: User created API-->>Admin: 201 Created else Email Exists Database-->>AuthService: User exists AuthService-->>API: Duplicate email API-->>Admin: 400 Bad Request end else Not Admin AuthMiddleware-->>API: Forbidden API-->>Admin: 403 Forbidden end else Invalid Token AuthMiddleware-->>API: Unauthorized API-->>Admin: 401 Unauthorized end

Request Body

{
  "username": "john_doe",
  "email": "[email protected]",
  "password": "password123",
  "role": "user"
}

Success Response (201 Created)

{
  "status": true,
  "message": "User berhasil didaftarkan",
  "data": {
    "id": 1,
    "username": "john_doe",
    "email": "[email protected]",
    "role": "user"
  }
}

Error Scenarios

Status Scenario Response
400 Validation error (missing fields, invalid email) Validation error details
401 No token or invalid token Unauthorized - Not logged in
403 User is not admin Forbidden - Not an admin

📅 Attendance Management

Attendance endpoints untuk mengelola data absensi dari ZKTeco device.

GET /api/v1/attendance Attendance

Summary: Get all attendance records (cached)

🔄 Get Attendance Flow

sequenceDiagram participant Client participant API participant Cache participant Database Client->>API: GET /api/v1/attendance API->>Cache: Check cache key alt Cache Hit Cache-->>API: Return cached data API-->>Client: 200 OK (from cache) else Cache Miss API->>Database: SELECT * FROM attendance Database-->>API: Attendance records API->>Cache: Store in cache (TTL: 5min) API-->>Client: 200 OK (from DB) end
POST /api/v1/attendance/device/{deviceId}/sync Attendance Async Job

Summary: Sync attendance from device to database (ASYNC with queue)

🔄 Async Sync Flow

sequenceDiagram participant Client participant API participant Queue participant Worker participant Device participant Database participant Cache Client->>API: POST /attendance/device/1/sync API->>Queue: Add sync job Queue-->>API: Job ID API-->>Client: 202 Accepted (job queued) Note over Queue,Worker: Background Processing Queue->>Worker: Process job Worker->>Device: TCP Connect Device-->>Worker: Attendance logs loop For each log Worker->>Database: INSERT/UPDATE attendance end Worker->>Cache: Clear attendance cache Worker->>Queue: Job completed Queue->>Database: Update job status

💡 Async Processing Benefits:

  • Non-blocking - API responds immediately dengan status 202
  • Reliable - Job retry mechanism jika gagal
  • Scalable - Multiple workers dapat memproses job secara parallel
  • Monitoring - Track job progress via queue stats endpoint

📋 Response Examples

// 202 Accepted Response
{
  "status": true,
  "message": "Sync job queued successfully",
  "data": {
    "job_id": "sync-device-1-20240205143000",
    "device_id": 1,
    "status": "queued",
    "queued_at": "2024-02-05T14:30:00Z"
  }
}

📱 Device Management

POST /api/v1/devices Device Management

Summary: Create new device configuration

🔄 Device Registration Flow

sequenceDiagram participant Client participant API participant Validation participant DeviceService participant Database participant ZKDevice Client->>API: POST /api/v1/devices Note over Client,API: {name, ip, port, password} API->>Validation: Validate request alt Valid Data Validation->>DeviceService: createDevice(data) DeviceService->>Database: Check IP exists alt IP Available DeviceService->>ZKDevice: Test Connection alt Connection OK ZKDevice-->>DeviceService: Connected DeviceService->>Database: INSERT device Database-->>DeviceService: device_id DeviceService-->>API: Device created API-->>Client: 201 Created else Connection Failed ZKDevice-->>DeviceService: Connection error DeviceService-->>API: Cannot reach device API-->>Client: 400 Bad Request end else IP Exists Database-->>DeviceService: Duplicate IP DeviceService-->>API: IP already registered API-->>Client: 409 Conflict end else Invalid Data Validation-->>API: Validation errors API-->>Client: 400 Bad Request end

Request Body

{
  "name": "Main Entrance Reader",
  "ip": "192.168.1.100",
  "port": 4370,
  "password": "",
  "location": "Building A - Main Entrance",
  "serial_number": "ZKT-001-2024"
}

Success Response (201 Created)

{
  "status": true,
  "message": "Device registered successfully",
  "data": {
    "id": 1,
    "name": "Main Entrance Reader",
    "ip": "192.168.1.100",
    "port": 4370,
    "location": "Building A - Main Entrance",
    "serial_number": "ZKT-001-2024",
    "status": "active",
    "is_connected": true,
    "created_at": "2024-02-05T14:30:00Z"
  }
}

Data Flow Table

Step Action Success Failure
1 Validate request data Continue 400 - Validation error
2 Check IP uniqueness Continue 409 - IP already exists
3 Test TCP connection Continue 400 - Cannot reach device
4 Insert to database 201 Created 500 - Database error

⚙️ Device Operations

GET /api/v1/devices/{deviceId}/info Device Operations

Summary: Get device information and status

🔄 Device Info Flow

sequenceDiagram participant Client participant API participant Database participant ZKDevice Client->>API: GET /devices/1/info API->>Database: Get device config Database-->>API: Device data API->>ZKDevice: Connect via TCP alt Connected ZKDevice-->>API: Device info Note over API,ZKDevice: Model, firmware,
capacity, users count API-->>Client: 200 OK + device info else Connection Failed ZKDevice-->>API: Connection timeout API-->>Client: 503 Service Unavailable end
POST /api/v1/devices/{deviceId}/restart Device Operations Critical Operation

Summary: Restart the device

⚠️ Critical Operation Warning:

Restarting device akan:

  • Disconnect semua active connections
  • Device offline selama ~30-60 seconds
  • Attendance logging ter-interupsi sementara
  • Requires admin authorization

🔄 Restart Flow

sequenceDiagram participant Admin participant API participant Database participant ZKDevice participant NotifService Admin->>API: POST /devices/1/restart API->>Database: Get device info Database-->>API: Device config API->>ZKDevice: Send restart command alt Restart Success ZKDevice-->>API: Restart initiated API->>Database: Log restart event API->>NotifService: Send admin notification NotifService-->>Admin: Email/Slack notification API-->>Admin: 200 OK Note over ZKDevice: Device rebooting... Note over ZKDevice: ~30-60 seconds Note over ZKDevice: Device back online else Restart Failed ZKDevice-->>API: Command failed API->>Database: Log error API-->>Admin: 500 Internal Error end

👥 User Management

POST /api/v1/users/device/{deviceId} User Management

Summary: Add user to device

🔄 Add User Flow

sequenceDiagram participant Client participant API participant Database participant ZKDevice participant FingerprintScanner Client->>API: POST /users/device/1 Note over Client,API: {user_id, name} API->>Database: Check user exists alt User New API->>ZKDevice: Connect ZKDevice-->>API: Connected API->>ZKDevice: Add user command ZKDevice->>FingerprintScanner: Register fingerprint Note over FingerprintScanner: User scans finger
3 times for enrollment alt Fingerprint Enrolled FingerprintScanner-->>ZKDevice: Template saved ZKDevice-->>API: User added API->>Database: Save user mapping API-->>Client: 201 Created else Enrollment Failed FingerprintScanner-->>ZKDevice: Quality too low ZKDevice-->>API: Enrollment failed API-->>Client: 400 Bad Request end else User Exists Database-->>API: User found API-->>Client: 409 Conflict end
POST /api/v1/users/device/{deviceId}/syncUserToDb User Management Async Job

Summary: Sync users from device to database (ASYNC with queue)

🔄 User Sync Flow (Async)

graph TB Start([Client Request]) --> Queue[Add to Queue] Queue --> Worker[Background Worker] Worker --> Connect[Connect to Device] Connect --> GetUsers[Get All Users] GetUsers --> Loop{For Each User} Loop -->|Process| CheckDB[Check if User Exists in DB] CheckDB -->|New| Insert[INSERT User] CheckDB -->|Existing| Update[UPDATE User] Insert --> Next{More Users?} Update --> Next Next -->|Yes| Loop Next -->|No| ClearCache[Clear User Cache] ClearCache --> Complete([Job Complete]) Queue -.->|Immediate Response| Client([202 Accepted]) style Start fill:#e1f5ff style Client fill:#d1fae5 style Queue fill:#fef3c7 style Worker fill:#dbeafe style Complete fill:#d1fae5

💡 Sync Strategy:

  • Async Processing: Large user sync di-process di background
  • Batch Operations: Insert/update users in batches (100 users/batch)
  • Progress Tracking: Monitor via GET /api/v1/queue/stats
  • Error Recovery: Failed jobs automatically retry 3 times

📊 Sync Performance

User Count Estimated Time Processing Method
1-100 ~5-10 seconds Sync (real-time)
100-1000 ~1-2 minutes Async (background)
1000+ ~5-10 minutes Async with batching

🚪 Door Control

POST /api/v1/devices/{deviceId}/unlock Door Control Security Sensitive

Summary: Unlock door remotely

🔒 Security Requirements:

  • Requires admin authorization
  • All unlock events are logged with timestamp & user
  • Audit trail stored for compliance
  • Rate limited to prevent abuse (10 requests/minute)

🔄 Remote Unlock Flow

sequenceDiagram participant Admin participant API participant RateLimit participant AuditLog participant ZKDevice participant DoorLock participant NotifService Admin->>API: POST /devices/1/unlock API->>RateLimit: Check rate limit alt Within Limit RateLimit-->>API: OK API->>AuditLog: Log unlock attempt AuditLog-->>API: Logged API->>ZKDevice: Send unlock command ZKDevice->>DoorLock: Trigger relay DoorLock-->>ZKDevice: Unlocked Note over DoorLock: Door unlocked
for 5 seconds ZKDevice-->>API: Success API->>AuditLog: Update status: success API->>NotifService: Alert security team API-->>Admin: 200 OK Note over DoorLock: Auto-lock after
5 seconds else Rate Limit Exceeded RateLimit-->>API: Too many requests API-->>Admin: 429 Too Many Requests end

📋 Unlock Response

// Success Response
{
  "status": true,
  "message": "Door unlocked successfully",
  "data": {
    "device_id": 1,
    "unlock_time": "2024-02-05T14:30:00Z",
    "unlocked_by": "[email protected]",
    "auto_lock_in": 5,
    "audit_id": "AUD-20240205-001"
  }
}

⚡ Queue & Cache Management

GET /api/v1/queue/stats Queue

Summary: Get queue statistics

📊 Queue Monitoring

// Queue Stats Response
{
  "status": true,
  "data": {
    "total_jobs": 1523,
    "active": 5,
    "waiting": 12,
    "completed": 1480,
    "failed": 26,
    "queues": {
      "attendance-sync": {
        "active": 2,
        "waiting": 5,
        "completed": 850
      },
      "user-sync": {
        "active": 3,
        "waiting": 7,
        "completed": 630
      }
    },
    "last_updated": "2024-02-05T14:30:00Z"
  }
}
POST /api/v1/cache/clear Cache

Summary: Clear all cache

🔄 Cache Clear Flow

graph LR A[Admin Request] --> B{Auth Check} B -->|Admin| C[Clear Redis Cache] B -->|Not Admin| D[403 Forbidden] C --> E[Log Cache Clear] E --> F[Notify Services] F --> G[200 Success] style A fill:#e1f5ff style C fill:#fee2e2 style G fill:#d1fae5 style D fill:#fee2e2

⚠️ Cache Clear Impact:

Clearing cache akan:

  • Temporary performance degradation (data akan di-fetch dari DB)
  • Cache akan rebuild gradually seiring requests masuk
  • Useful setelah bulk updates atau data migrations

✅ Best Practices & Integration Guide

🔐 Authentication Flow

Recommended Auth Implementation:

  1. User logs in → Receive access_token & refresh_token
  2. Store tokens securely (HttpOnly cookies recommended)
  3. Include access_token in Authorization header: Bearer {token}
  4. When access_token expires (401), use refresh_token to get new tokens
  5. If refresh_token expires, redirect to login

⚡ Performance Optimization

Feature Strategy Benefit
Caching Redis cache with 5-minute TTL Reduce DB load, faster response
Async Processing Queue-based background jobs Non-blocking operations, better UX
Batch Operations Process 100 records/batch Efficient bulk operations
Connection Pooling Reuse device connections Reduce connection overhead

🔒 Security Checklist

Security Implementation Checklist:

  • ✅ Always use HTTPS in production
  • ✅ Implement rate limiting on all endpoints
  • ✅ Validate and sanitize all inputs
  • ✅ Log all security-sensitive operations
  • ✅ Use environment variables for secrets
  • ✅ Implement CORS properly
  • ✅ Regular security audits

📝 Error Handling

// Standard Error Response Format
{
  "status": false,
  "message": "Human-readable error message",
  "error": {
    "code": "ERROR_CODE",
    "type": "ErrorType",
    "details": "Additional error details or validation errors"
  },
  "metadata": {
    "timestamp": "2024-02-05T14:30:00Z",
    "request_id": "req-abc-123",
    "api_version": "v1"
  }
}

📚 ZKTeco Device API Documentation

Version 1.0.1

For API support, contact: danishluthfim@gmail.com