A comprehensive Node.js implementation of the ZKTeco PUSH communication protocol for syncing user and biometric data across multiple ZKTeco devices.
- Device registration and management
- User information synchronization
- Biometric template management (fingerprint, face, finger vein, unified templates)
- User photo and comparison photo handling
- Work code management
- ID card information processing
- Real-time data synchronization across devices
- Multi-device support with automatic sync
- Command queuing and execution tracking
- Heartbeat monitoring and connection management
- Attendance record management
- Communication encryption
- Operation log processing for attendance
# Install dependencies
npm install
# Start the server
npm start
# For development with auto-reload
npm run devThe server runs on port 8080 by default. Set PORT environment variable to change:
PORT=3000 npm startConfigure your ZKTeco devices to connect to this server:
- Server IP: Your server's IP address
- Server Port: 8080 (or your configured port)
- Protocol: PUSH
- Server (server.js) - Main HTTP server handling ZK protocol endpoints
- Database (database.js) - SQLite database layer with full schema
- Device Manager (deviceManager.js) - Device registration and configuration
- Command Manager (commandManager.js) - Command queue and execution
- Data Processor (dataProcessor.js) - Data parsing and synchronization
Main tables:
devices- Device registration and statususers- User information and credentialsfingerprint_templates- Fingerprint biometric dataface_templates- Face biometric databio_templates- Unified biometric templatesuser_photos- User profile photoscomparison_photos- Biometric comparison photoscommands- Command queue and execution trackingsync_log- Data synchronization logging
GET /iclock/cdata- Device initialization and configuration exchangePOST /iclock/cdata- Data upload from devices (users, templates, photos)GET /iclock/getrequest- Command requests from devicesPOST /iclock/devicecmd- Command replies from devicesGET /iclock/ping- Heartbeat monitoring
GET /api/devices- List all devices with statusGET /api/devices/{serialNumber}- Get device detailsDELETE /api/devices/{serialNumber}- Remove deviceGET /api/users- List users (query: ?device=serialNumber)GET /api/users/{pin}- Get user details with biometricsDELETE /api/users/{pin}- Delete user and all related biometric dataGET /api/commands- List commands (query: ?device=&status=&limit=)POST /api/commands/user/add- Add user commandPOST /api/commands/user/delete- Delete user commandPOST /api/commands/device/reboot- Reboot device commandGET /api/status- System status and statisticsGET /api/stats- Detailed system statisticsPOST /api/sync/manual- Trigger manual synchronization between devices
Delete User API
DELETE /api/users/{pin}
Permanently deletes a user and all their associated biometric data (fingerprints, face templates, bio templates, photos) from the database. Additionally, automatically creates delete user commands for all active devices to sync the deletion across the entire system.
Manual Sync API
POST /api/sync/manual
Triggers manual synchronization of data to target devices. Can sync from a specific device or from the entire database.
Request body options:
Sync from Database to All Devices:
{
"syncType": "all" // Options: "all", "users", "fingerprints", "faces", "bio"
}Sync from Specific Device to Other Devices:
{
"sourceDevice": "device_serial_number",
"targetDevices": ["target1", "target2"], // Optional: if not provided, syncs to all active devices except source
"syncType": "all" // Options: "all", "users", "fingerprints", "faces", "bio"
}Response includes sync results, number of commands created, and detailed status for each target device.
- User Information (USERINFO)
- Fingerprint Templates (FINGERTMP)
- Face Templates (FACE)
- Finger Vein Templates (FVEIN)
- Unified Bio Templates (BIODATA)
- User Photos (USERPIC)
- Comparison Photos (BIOPHOTO)
- Work Codes (WORKCODE)
- ID Card Information (IDCARD)
When any device uploads data, the server automatically:
- Processes and stores the data
- Identifies all other active devices
- Creates sync commands for each device
- Queues commands for delivery
- Tracks synchronization status
This ensures all devices maintain consistent user and biometric data.
Supports all ZKTeco command types:
- Add/update users, templates, photos
- Delete user data and biometrics
- Query specific information
- Device reboot
- Door unlock
- Alarm control
- Set device options
- Reload configuration
- Remote fingerprint enrollment
- Remote biometric enrollment
- Based on ZKTeco PUSH Protocol v2.4.1
- Supports protocol versions 2.2.14 through 2.4.1
- Full HTTP/1.1 compliance
- Standard ZK message formatting
zk_server/
βββ server.js # Main application
βββ database.js # Database layer
βββ deviceManager.js # Device management
βββ commandManager.js # Command handling
βββ dataProcessor.js # Data processing
βββ package.json # Dependencies
βββ README.md # Documentation
ZKPushServer- Main server classDatabase- SQLite database wrapperDeviceManager- Device lifecycle managementCommandManager- Command queue operationsDataProcessor- Data parsing and sync logic
Comprehensive logging includes:
- Device connections/disconnections
- Data upload processing
- Command execution results
- Synchronization operations
- Error tracking
Get all devices:
curl http://localhost:8080/api/devicesAdd a user to a device:
curl -X POST http://localhost:8080/api/commands/user/add \
-H "Content-Type: application/json" \
-d '{
"deviceSerial": "DEVICE001",
"userInfo": {
"pin": "123",
"name": "John Doe",
"privilege": 0,
"card": "123456789"
}
}'Get system status:
curl http://localhost:8080/api/statusConfigure your ZKTeco device with these settings:
- Communication Mode: TCP/IP Push
- Server IP: Your server IP
- Server Port: 8080
- Push Protocol: Enabled
- Realtime: Enabled
MIT License
Issue: Previously, fingerprint and face templates worked separately but couldn't be properly synced for the same user due to competing protocols and storage conflicts.
Solution: Implemented a unified BIODATA approach that uses the ZKTeco protocol's modern unified biometric template format for all biometric types.
- Unified Protocol: All biometric templates (fingerprint, face, finger vein) now use the
DATA UPDATE BIODATAcommand format - Consistent Operations: Delete and query operations now use the same unified format as add operations
- Multi-Modal Support: Proper support for users with multiple biometric modalities
- Enhanced Validation: Better template data validation to prevent sync errors
- Bulk Operations: Support for adding multiple users with biometric data in one operation
- Granular Control: Individual biometric type deletion and querying
- Protocol Consistency: All CRUD operations (Create, Read, Update, Delete) use the same BIODATA format
- π₯ Delete-First Updates: NEW - Automatically deletes existing templates before adding new ones to prevent conflicts
- Update Operations: NEW - Dedicated update methods that ensure clean biometric data replacement
- β Delete Operations: Fixed inconsistency where deletes used legacy format while adds used BIODATA
- β Query Operations: Updated queries to use unified BIODATA format for consistency
- β Sync Conflicts: Eliminated conflicts between different template formats for the same user
- β Protocol Fragmentation: Unified all biometric operations under single protocol
- β Multi-Modal Users: Proper handling of users with both fingerprint and face templates
- β Template Validation: Enhanced validation prevents common sync errors
- β π₯ Template Update Conflicts: NEW - Automatically clears existing templates before updates to prevent conflicts
- β π₯ Stale Data Issues: NEW - Update operations ensure fresh biometric data without remnants
POST /api/users/biometric-add
Content-Type: application/json
{
"deviceSerial": "DEVICE123",
"userInfo": {
"pin": "001",
"name": "John Doe",
"privilege": 0
},
"biometrics": [
{
"type": "fingerprint",
"fid": 0,
"template": "base64_encoded_fingerprint_template",
"valid": 1
},
{
"type": "face",
"fid": 0,
"template": "base64_encoded_face_template",
"valid": 1
}
],
"updateMode": false // Optional: set to true to delete existing templates first
}PUT /api/users/biometric-update
Content-Type: application/json
{
"deviceSerial": "DEVICE123",
"userInfo": {
"pin": "001",
"name": "John Doe Updated",
"privilege": 0
},
"biometrics": [
{
"type": "fingerprint",
"fid": 0,
"template": "new_base64_encoded_fingerprint_template",
"valid": 1
},
{
"type": "face",
"fid": 0,
"template": "new_base64_encoded_face_template",
"valid": 1
}
]
}POST /api/users/bulk-biometric-add
Content-Type: application/json
{
"deviceSerial": "DEVICE123",
"usersData": [
{
"userInfo": {
"pin": "001",
"name": "John Doe",
"privilege": 0
},
"biometrics": [
{
"type": "fingerprint",
"fid": 0,
"template": "base64_template_1"
}
]
},
{
"userInfo": {
"pin": "002",
"name": "Jane Smith",
"privilege": 0
},
"biometrics": [
{
"type": "face",
"fid": 0,
"template": "base64_template_2"
}
]
}
]
}PUT /api/users/bulk-biometric-update
Content-Type: application/json
{
"deviceSerial": "DEVICE123",
"usersData": [
{
"userInfo": {
"pin": "001",
"name": "John Doe Updated",
"privilege": 0
},
"biometrics": [
{
"type": "fingerprint",
"fid": 0,
"template": "new_base64_template_1"
}
]
}
]
}DELETE /api/users/{pin}/biometrics
Content-Type: application/json
{
"deviceSerial": "DEVICE123"
}DELETE /api/users/{pin}/biometrics/{type}
Content-Type: application/json
{
"deviceSerial": "DEVICE123",
"fid": 0 // optional
}GET /api/users/{pin}/biometrics/{type}?deviceSerial=DEVICE123&fid=0POST /api/biometrics/validate
Content-Type: application/json
{
"templateData": {
"pin": "001",
"template": "base64_template_data",
"fid": 0
},
"biometricType": "fingerprint"
}POST /api/users/biometric-sync
Content-Type: application/json
{
"sourceDevice": "DEVICE123",
"targetDevice": "DEVICE456",
"pin": "001"
}The system now supports the following biometric types using the unified BIODATA format:
fingerprint(Type=1)face(Type=2)voiceprint(Type=3)iris(Type=4)retina(Type=5)palmprint(Type=6)fingervein(Type=7)palm(Type=8)visible_light_face(Type=9)
If you have existing systems using the legacy format:
- Automatic Conversion: The system automatically converts legacy FP and FACE sync operations to BIODATA format
- Backward Compatibility: Existing API calls to
addFingerprintTemplateandaddFaceTemplatestill work but now use the unified format internally - New Recommended Method: Use
addUserWithBiometricsfor new implementations
All biometric templates now use:
C:${CmdID}:DATA UPDATE BIODATA Pin=${PIN}\tNo=${FID}\tIndex=${INDEX}\tValid=${VALID}\tDuress=0\tType=${TYPE}\tMajorVer=0\tMinorVer=0\tFormat=ZK\tTmp=${TEMPLATE}
Templates are stored in a unified format in the bio_templates table with proper type identification.
If you still experience sync issues:
- Check the console logs for "π Converting" messages to confirm unified format is being used
- Verify template data is valid base64
- Ensure devices support the BIODATA format (newer ZKTeco devices)
- Use the
/api/users/biometric-syncendpoint to test sync between specific devices
The system maintains backward compatibility:
- Old
FINGERTMPandFACEcommands are automatically converted - Existing database records are preserved
- Legacy API endpoints continue to function
For best results with multi-modal biometric users, use the new unified endpoints and ensure all devices in your network support the BIODATA protocol format.
When updating biometric templates, the system now automatically deletes existing templates before adding new ones. This prevents:
- Template Conflicts: Old and new templates competing during verification
- Sync Issues: Mixed template formats causing sync failures
- Storage Bloat: Accumulation of outdated template data
- Authentication Problems: Stale templates interfering with user verification
Automatic Delete-First (Recommended):
# Use dedicated update endpoints - always deletes existing first
PUT /api/users/biometric-update # Single user update
PUT /api/users/bulk-biometric-update # Bulk user updateManual Control:
# Use add endpoints with updateMode flag
POST /api/users/biometric-add
{
"updateMode": true, # Deletes existing templates first
"userInfo": {...},
"biometrics": [...]
}Legacy Add (No Delete):
# Add without deleting (may cause conflicts)
POST /api/users/biometric-add
{
"updateMode": false, # Default - adds without deleting
"userInfo": {...},
"biometrics": [...]
}- For Updates: Always use
PUTendpoints or setupdateMode: true - For New Users: Use
POSTendpoints withupdateMode: false(default) - For Troubleshooting: Use clear endpoints to remove problematic templates first
- For Migration: Use bulk update endpoints to refresh all user data
When delete-first is active, you'll see:
ποΈ Deleting existing fingerprint templates for PIN 123 before adding new one
β
Existing fingerprint templates deleted for PIN 123
π§ Adding unified biometric template: PIN=123, Type=1 (fingerprint), FID=0