Skip to main content
This guide covers deploying the single-device server (servidor.py), which provides a straightforward REST API for managing one ZKTeco biometric device.

Overview

The single-device server is ideal for:
  • Small offices with one biometric device
  • Testing and development environments
  • Simple deployment scenarios without device management overhead
All API requests query the device in real-time without data persistence.

Prerequisites

1

Install Dependencies

Install the required Python packages:
pip install flask pyopenssl pyzk
2

Device Network Configuration

Ensure your ZKTeco device is:
  • Connected to the same network as your server
  • Accessible via its IP address
  • Using the default port (4370) or note the custom port

Environment Variables

Configure the server by setting these environment variables before starting:

Device Connection

export ZK_IP="192.168.1.205"
export ZK_PORT="4370"
export ZK_PASSWORD="0"
export ZK_TIMEOUT="5"
VariableDefaultDescription
ZK_IP192.168.1.205IP address of the ZKTeco device
ZK_PORT4370Port number of the device
ZK_PASSWORD0Device password (typically 0)
ZK_TIMEOUT5Connection timeout in seconds

Server Configuration

export API_HOST="0.0.0.0"
export API_PORT="5000"
export CERT_FILE="cert.pem"
export KEY_FILE="key.pem"
VariableDefaultDescription
API_HOST0.0.0.0Server listening interface
API_PORT5000Server port
CERT_FILEcert.pemSSL certificate file path
KEY_FILEkey.pemSSL private key file path

Starting the Server

python servidor.py
The server will:
  1. Check for existing SSL certificates
  2. Generate self-signed certificates if pyopenssl is installed
  3. Start in HTTPS mode (with certificates) or HTTP mode (without)

Verifying the Connection

After starting the server, verify the setup:
1

Check Server Health

curl http://localhost:5000/
Expected response:
{
  "status": "online",
  "device_ip": "192.168.1.205",
  "device_port": 4370,
  "timestamp": "2026-03-06 10:30:00"
}
2

Query Device Information

curl http://localhost:5000/device/info
Expected response:
{
  "success": true,
  "data": {
    "serialnumber": "BNVR123456789",
    "device_name": "ZKTeco Device",
    "platform": "ZEM560",
    "firmware_version": "Ver 6.60",
    "users_count": 42,
    "device_time": "2026-03-06 10:30:15"
  }
}
3

Retrieve Attendance Records

curl http://localhost:5000/attendance
# Filter by user
curl "http://localhost:5000/attendance?user_id=5"

# Filter by date
curl "http://localhost:5000/attendance?date=2026-03-06"

Common Operations

User Management

curl http://localhost:5000/users
Response includes uid, user_id, name, privilege, and card for each user.
curl -X POST http://localhost:5000/users \
  -H "Content-Type: application/json" \
  -d '{
    "user_id": "123",
    "name": "Juan Perez",
    "password": "",
    "privilege": 0,
    "card": 0
  }'
Privilege Levels:
  • 0 - Regular user
  • 14 - Administrator
curl -X PUT http://localhost:5000/users/123 \
  -H "Content-Type: application/json" \
  -d '{
    "name": "Juan Perez Updated",
    "privilege": 0
  }'
All fields are optional. Only provided fields will be updated.
curl -X DELETE http://localhost:5000/users/123

Fingerprint Enrollment

1

Start Enrollment Mode

Activate fingerprint enrollment for a user:
curl -X POST http://localhost:5000/users/123/enroll-finger \
  -H "Content-Type: application/json" \
  -d '{
    "finger_index": 0
  }'
Finger Index Values:
  • 0 - Right thumb
  • 1 - Right index finger
  • 2 - Right middle finger
  • 3 - Right ring finger
  • 4 - Right little finger
  • 5 - Left thumb
  • 6 - Left index finger
  • 7 - Left middle finger
  • 8 - Left ring finger
  • 9 - Left little finger
2

User Places Finger

The device enters enrollment mode. The user must place their finger on the device 3 times when prompted.
3

Verify Enrollment

Check registered fingerprints:
curl http://localhost:5000/users/123/fingers
Response:
{
  "success": true,
  "user_id": "123",
  "name": "Juan Perez",
  "total_fingers": 2,
  "data": [
    {
      "finger_index": 0,
      "finger_name": "Pulgar derecho",
      "valid": true
    },
    {
      "finger_index": 1,
      "finger_name": "Indice derecho",
      "valid": true
    }
  ]
}

Device Time Management

curl http://localhost:5000/device/time

Deployment Scenarios

Local Network Access

# Server at 192.168.1.100
ZK_IP="192.168.1.205" \
API_HOST="0.0.0.0" \
API_PORT="5000" \
python servidor.py
Access from any device on the network:
curl http://192.168.1.100:5000/attendance

Internet-Facing Deployment

When exposing to the internet, always use HTTPS and implement additional authentication.
1

Use Reverse Proxy

Use Nginx or Apache with SSL certificates:
server {
    listen 443 ssl;
    server_name biometric.example.com;

    ssl_certificate /etc/letsencrypt/live/biometric.example.com/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/biometric.example.com/privkey.pem;

    location / {
        proxy_pass http://127.0.0.1:5000;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
    }
}
2

Configure Firewall

# Allow only specific IPs if possible
sudo ufw allow from 203.0.113.0/24 to any port 5000
3

Add Authentication Layer

Consider implementing API keys or OAuth 2.0 for production deployments.

Troubleshooting

Error: Connection timeout or Unable to connect to deviceSolutions:
  • Verify the device IP address is correct
  • Check network connectivity: ping 192.168.1.205
  • Ensure the device port is accessible
  • Increase ZK_TIMEOUT environment variable
  • Check firewall rules on both server and device
Error: SSL certificate verification failedSolutions:
  • If using self-signed certificates, use -k flag with curl:
    curl -k https://localhost:5000/
    
  • For production, use proper SSL certificates (Let’s Encrypt)
  • Disable HTTPS by not installing pyopenssl
Error: Device is locked or Device busySolutions:
  • The device can handle only one connection at a time
  • Wait for previous request to complete
  • Restart the device if it remains locked
  • Check for other applications connected to the device
Error: Attendance endpoint returns empty arraySolutions:
  • Verify users have clocked in/out on the device
  • Check the device’s internal memory
  • Verify date filters aren’t excluding records
  • Ensure device time is synchronized

Performance Considerations

The single-device server queries the device in real-time for every request. Large attendance datasets may take longer to retrieve.
  • Attendance Records: Retrieving thousands of records may take 5-30 seconds depending on device model
  • Concurrent Requests: The server uses threading locks to prevent simultaneous device access
  • Network Latency: Keep server and device on the same local network for best performance

Next Steps

Multi-Device Setup

Scale to multiple devices with centralized management

SSL Configuration

Secure your deployment with proper SSL/TLS

API Reference

Complete API endpoint documentation

Environment Variables

Full configuration reference

Build docs developers (and LLMs) love