A Node.js API server and real-time Socket.IO service that streams attendance data from a ZKTeco device. Attendance snapshots are fetched on a schedule, published via Redis Pub/Sub, and exposed over REST and WebSocket endpoints. Easily test or demo your setup with built-in Ngrok integration.
- REST API:
GET /api/v1/bio-syncreturns the latest attendance snapshot as JSON. - Real-time updates:
Socket.IOstream uses MsgPack to push incremental attendance events to clients. - Redis Pub/Sub: Decouple data capture from client distribution; in-memory fallback when Redis is unavailable.
- Ngrok Integration: Quickly expose your local server over HTTPS for remote testing or demos.
- Node.js v22
- npm or Yarn
- ZKTeco biometric device on your network
- Redis instance (host, port, credentials)
- Ngrok account (for public tunneling)
- Copy the
.env.exampleto.envin the project root. - Update variables in
.envas needed (ensure.envis in.gitignore):
# Redis
REDIS_HOST=your.redis.host
REDIS_PORT=6379
REDIS_USERNAME=default
REDIS_PASSWORD=your_redis_password
REDIS_CHANNEL=attendance:updates
# ZKTeco Device
DEVICE_IP=192.168.1.201 # ZKTeco device IP address
DEVICE_PORT=4370
SEND_TIMEOUT=20000 # in milliseconds
RECV_TIMEOUT=20000 # in milliseconds
# Server
SERVER_PORT=8090
CLIENT_ORIGIN=http://localhost:3000 # frontend URL for CORS# Clone repository
git clone https://github.com/itechxcellence/dtr.zkteco.api.git
cd dtr.zkteco.api
# Install dependencies
npm install
# or
yarn install-
Ensure Redis is running and accessible per
.envsettings. -
Confirm your ZKTeco device is configured and reachable.
-
Start the API server:
node index.js
The server listens on localhost:${SERVER_PORT} by default.
-
Install and authenticate Ngrok.
-
Run:
ngrok http ${SERVER_PORT} -
Use the generated public HTTPS URL for both REST and Socket.IO clients.
- URL:
GET /api/v1/bio-sync - Response: JSON array of the latest attendance records.
curl https://<ngrok-id>.ngrok.app/api/v1/bio-syncClients can subscribe to live updates:
import { Server } from 'socket.io';
import msgpack from 'msgpack-lite';
const io = new Server(server, {
cors: { origin: CLIENT_ORIGIN, methods: ['GET','POST'] },
transports: ['websocket'],
});
// Socket.IO connection handling
io.on('connection', socket => {
console.log(`Client connected: ${socket.id}`);
if (last_payload_obj) {
socket.emit('attendance', msgpack.encode(last_payload_obj));
}
const message_handler = (_ch, msg) => {
socket.emit('attendance', msg);
};
sub_client.on(REDIS_CHANNEL, message_handler);
socket.on('disconnect', () => {
sub_client.off(REDIS_CHANNEL, message_handler);
});
});Use Task Scheduler or NSSM to run the server and Ngrok on boot:
-
Ngrok config (
%USERPROFILE%\AppData\Local\ngrok\ngrok.yml):version: "3" agent: authtoken: YOUR_NGROK_AUTHTOKEN crl_noverify: true # For Development only! update_check: false # For Development only! tunnels: attendance: proto: http addr: ${SERVER_PORT} basic_auth: - "user:password"
-
Create Windows services for both
node index.jsand Ngrok executable.
- .env: Keep out of source control (
.gitignore) and restrict tochmod 600on Linux/macOS. - HTTPS: Always use the Ngrok HTTPS URL or your own SSL setup in production.
- Credentials Rotation: Rotate Redis and Ngrok tokens periodically.
- Access Control: Protect endpoints via CORS, Basic Auth, or API keys.
We welcome suggestions, feature requests, and improvements! Please use one of the following channels:
- Issues & Pull Requests: Open or comment on issues at https://github.com/itechxcellence/dtr.zkteco.api/issues
- Email: Send suggestions/discussions to ronzape@ronhedwigzape.com
Feel free to fork the repo, make changes, and submit a pull request.
MIT © ItechXcellence