Timmy Device Manager — API Reference
This page documents the backend HTTP APIs and example cURL requests. All authenticated endpoints require Authorization: Bearer <JWT>.
How to get a token (Login)
Use this endpoint to obtain JWT used in subsequent requests.
POST /api/auth/login — public
Request body (JSON)
{
"email": "admin@timmy.local",
"password": "admin123"
}
cURL
curl -s -X POST http://localhost:9090/api/auth/login \
-H "Content-Type: application/json" \
-d '{"email":"admin@timmy.local","password":"admin123"}'
Successful response
{
"success": true,
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6...",
"user": { "email":"admin@timmy.local","name":"Admin","role":"ADMIN" }
}
Queue / Operation model (general)
The system records every device-related action as an Operation document in MongoDB. Typical operation fields:
{
"_id": "64f5...abc",
"sn": "ZXRE06022863",
"type": "setuserinfo", // command name sent to device
"payload": { ... }, // original payload sent
"response": { ... }, // device response (if any)
"status": "pending|sent|success|failed|canceled",
"attemptCount": 0,
"lastError": "...",
"createdAt": "2025-11-08T10:00:00.000Z"
}
When using the documented endpoints that send commands, you'll receive a JSON with at minimum success and an op object or queued/ note describing the result.
Operations listing (filtering & paging)
List stored operation records with filters, date range and paging.
GET /api/operations — auth required
Query parameters
page=1 // default
limit=20 // default
sn=ZXRE06022863 // optional
type=setuserinfo // optional
status=failed // optional
from=YYYY-MM-DD // optional (createdAt >= from)
to=YYYY-MM-DD // optional (createdAt <= to)
cURL
curl -s "http://localhost:9090/api/operations?page=1&limit=20&sn=ZXRE06022863&from=2025-11-01&to=2025-11-10" \
-H "Authorization: Bearer $TOKEN"
Example Response
{
"success": true,
"total": 123,
"page": 1,
"items": [
{
"_id": "...",
"sn": "ZXRE06022863",
"type": "setuserinfo",
"payload": { ... },
"response": { ... },
"status": "success",
"attemptCount": 1,
"createdAt": "2025-11-08T10:00:00.000Z"
},
...
]
}
Operation actions: Cancel / Retry
Cancel or request immediate retry for a recorded operation.
POST /api/operations/:id/cancel — auth required
curl -s -X POST http://localhost:9090/api/operations/64f5...abc/cancel \
-H "Authorization: Bearer $TOKEN"
Response (example)
{
"success": true,
"op": { "_id":"64f5...abc", "status":"canceled", ... }
}
POST /api/operations/:id/retry — auth required
curl -s -X POST http://localhost:9090/api/operations/64f5...abc/retry \
-H "Authorization: Bearer $TOKEN"
Response (example)
{
"success": true,
"queued": true,
"op": { "_id":"64f5...abc", "status":"pending", "attemptCount": 2 }
}
Stats
Aggregate counts by status / type
GET /api/stats — auth required
curl -s http://localhost:9090/api/stats -H "Authorization: Bearer $TOKEN"
Example response
{
"success": true,
"total": 123,
"byStatus": [{ "_id":"success","count":80 }, { "_id":"failed","count":20 }, ...],
"byType": [{ "_id":"setuserinfo","count":90 }, ...]
}
Device users (read full list)
Ask the device for full users list (this creates an operation record and communicates with the device).
GET /api/device/:sn/users — auth required
curl -s http://localhost:9090/api/device/ZXRE06022863/users \
-H "Authorization: Bearer $TOKEN"
Success response (device must be online)
{
"success": true,
"records": [
{ "enrollid": 1, "name":"John", "aliasid":"J1", "backupnum":50, "record":"..." },
{ "enrollid": 2, "name":"Sally", "backupnum":2, "template":"..." }
],
"raw": { /* raw device response object */ }
}
If the device is offline, you'll receive: {success:false, error:'device_offline_or_not_registered'}
Bulk delete users on a device
Delete multiple enroll IDs from a single device (creates operations for each delete)
POST /api/device/:sn/delete-users — auth required
Request body
{
"enrollIds": [2,3,15]
}
cURL
curl -s -X POST http://localhost:9090/api/device/ZXRE06022863/delete-users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"enrollIds":[2,3,15]}'
Response (example)
{
"success": true,
"sn": "ZXRE06022863",
"count": 3,
"results": [
{ "enrollid": 2, "opId":"64f...", "status":"pending" },
{ "enrollid": 3, "opId":"650...", "status":"pending" }
]
}
Transfer / Copy users (device → device)
Copy or move (copy + delete from source) users from one device to another. The endpoint will create multiple sub-operations: fetch user backup blocks from source, push to target, optionally delete on source.
POST /api/transfer-users — auth required
Request body
{
"fromSn": "ZXRE06022863",
"toSn": "TYSG18086518",
"enrollIds": [2,3], // optional: if absent => transfer all users
"deleteFromSource": false // true = move, false = copy
}
cURL
curl -s -X POST http://localhost:9090/api/transfer-users \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"fromSn":"ZXRE06022863","toSn":"TYSG18086518","enrollIds":[2,3],"deleteFromSource":true}'
Example response
{
"success": true,
"fromSn": "ZXRE06022863",
"toSn": "TYSG18086518",
"results": [
{
"enrollid": 2,
"steps": [
{ "backupnum": 50, "action":"fetch", "result":"success" },
{ "backupnum": 50, "action":"push", "opId":"64f...", "result":"pending" },
{ "action":"delete_from_source", "opId":"650...", "result":"pending" }
]
}
]
}
Add new user to a device
This endpoint sends an
adduserinfo command to a connected device to register a new user (fingerprint or face).
The device must be
online.
No record field is required — the device will create the biometric template internally.
Use backupnum to indicate the biometric type:
backupnum = 0 → Fingerprint user
backupnum = 50 → Face user
POST /api/device/:sn/add-user — auth required
Request body (JSON)
{
"enrollid": 10012,
"name": "John Smith1",
"aliasid": "JSMITH1",
"backupnum": 50
}
Example cURL
curl -s -X POST http://localhost:9090/api/device/ZXRE06022863/add-user \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enrollid": 10012,
"name": "John Smith1",
"aliasid": "JSMITH1",
"backupnum": 50
}'
Successful response (example)
{
"success": true,
"opId": "673bd98fa14b34d6c9db2009",
"status": "success",
"response": {
"ret": "adduser",
"result": true
}
}
If the device is offline you'll receive { "success": false, "error": "device_offline_or_not_registered" }.
Each request is logged as an Operation document of type adduserinfo.
Clean all logs from a device
Sends the cleanlog command to a connected device to erase all attendance records stored locally on that device.
The device must be online.
POST /api/device/:sn/clean-log — auth required
No request body is needed.
Example cURL
curl -s -X POST http://localhost:9090/api/device/ZXRE06022863/clean-log \
-H "Authorization: Bearer $TOKEN"
Response (example)
{
"success": true,
"opId": "673bd98fa14b34d6c9db2009",
"status": "success",
"response": {
"ret": "cleanlog",
"result": true
}
}
A corresponding Operation entry of type cleanlog is recorded in MongoDB for audit tracking.
Forward device logs (optional)
Devices can forward logs to your server via /api/device-log. The server will attempt to forward these logs to configured FORWARD_LOG_URL.
POST /api/device-log
curl -s -X POST http://localhost:9090/api/device-log \
-H "Content-Type: application/json" \
-d '{"sn":"ZXRE06022863","record":[ { "enrollid":2, "time":"2025-11-08T09:00:00" } ] }'
Response
{
"success": true,
"forwarded": false,
"retryLater": true
}
Employee APIs (login & management)
These endpoints manage employees used by the mobile app. Admins can create/edit employees; employees can log in with their username/password.
POST /api/employees/login — public
Request body (JSON)
{
"username": "emp-86359.mo",
"password": "password123"
}
cURL
curl -s -X POST http://localhost:9090/api/employees/login \
-H "Content-Type: application/json" \
-d '{"username":"emp-86359.mo","password":"password123"}'
Example response
{
"message": "Login successful",
"token": "eyJhbGciOiJIUzI1NiIsInR5cCI6...",
"result": {
"_id": "692553de39586fb9c712e3cd",
"enroll_id": "86359",
"name": "Employee Name",
"username": "emp-86359.mo",
"owner": "679a312fba856722da62098d",
"app_permissions": {
"can_login_app": true,
"can_view_fingerprint": true,
"...": false
},
"...": "... other fields ..."
}
}
GET /api/employees — auth (admin)
List employees for the current owner with optional search.
Query parameters
q=... // optional text filter on username / fullName / phone / email
cURL
curl -s "http://localhost:9090/api/employees?q=mustafa" \
-H "Authorization: Bearer $TOKEN"
Response (example)
{
"success": true,
"items": [
{
"_id": "69256416bd792a2ff963a6c9",
"enroll_id": "121",
"username": "asd",
"fullName": "mustafa",
"phone": "",
"email": "",
"isActive": true,
"owner": "690f78b6dcccc75fb6722fe2",
"createdAt": "2025-11-25T..."
}
]
}
POST /api/employees — auth (admin)
Create a new employee (used by the mobile app).
Request body
{
"enroll_id": "121",
"username": "asd",
"password": "strongPassword",
"fullName": "mustafa",
"phone": "0770xxxxxxx",
"email": "mustafa@example.com"
}
cURL
curl -s -X POST http://localhost:9090/api/employees \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{
"enroll_id":"121",
"username":"asd",
"password":"strongPassword",
"fullName":"mustafa"
}'
PUT /api/employees/:id — auth (admin)
Update existing employee (partial update).
curl -s -X PUT http://localhost:9090/api/employees/69256416bd792a2ff963a6c9 \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{"fullName":"Mustafa Updated","phone":"0770xxxxxxx"}'
DELETE /api/employees/:id — auth (admin)
curl -s -X DELETE http://localhost:9090/api/employees/69256416bd792a2ff963a6c9 \
-H "Authorization: Bearer $TOKEN"
Mobile fingerprints — create & forward to 2nd server
These endpoints handle attendance logs coming from the mobile app, store them as FingerPrintLog documents, and optionally forward them to a second server (e.g. /api/checkinout/save).
POST /api/fingerprints/app — auth (employee)
Create a fingerprint log from the mobile app and forward to the client server.
Request body
{
"event": 1,
"location": {
"latitude": 33.3096307,
"longitude": 44.4490251
},
"device_sn": "App",
"device_name": "App",
"macs": "aa:bb:cc:dd:ee:ff",
"image": "data:image/jpeg;base64,... (optional)"
}
cURL (employee JWT token)
curl -s -X POST http://localhost:9090/api/fingerprints/app \
-H "Authorization: Bearer $EMPLOYEE_TOKEN" \
-H "Content-Type: application/json" \
-d '{
"event": 1,
"location": { "latitude":33.30963, "longitude":44.44902 },
"device_sn": "App",
"device_name": "App",
"macs": "aa:bb:cc:dd:ee:ff"
}'
Response (example)
{
"success": true,
"message": "تم تسجيل بصمة الموبايل بنجاح",
"data": {
"_id": "6925d3b4c8227c3a1972328b",
"enrollid": "121",
"event": 1,
"time": "2025-11-25T16:05:08.665Z",
"device_sn": "App",
"device_type": "mobile_app",
"is_send": true,
"send_failed": false,
"forwardedAt": "2025-11-25T16:05:09.000Z",
"forwardResponse": { "success": true, "forwarded": true },
"...": "..."
},
"forwarded": true
}
Forward URL and token are configured via
FORWARD_FINGERPRINT_URL / FORWARD_LOG_URL and
FORWARD_FINGERPRINT_TOKEN / FORWARD_LOG_TOKEN in
.env.
The payload forwarded to the client looks like:
{
"sn": "App",
"record": [
{
"enrollid": 121,
"time": "2025-11-25T16:05:08.665Z",
"event": 1
}
]
}
Mobile fingerprints — listing (employee & admin)
Employee endpoints return their own logs, while admin endpoints list all mobile logs with filters and pagination.
GET /api/fingerprints/employee — auth (employee)
List fingerprint logs for the current employee.
Query parameters (all optional)
from=ISO8601 // filter by time >= from
to=ISO8601 // filter by time <= to
event=1 // filter by event code
device_sn=App // filter by device
page=1 // default
limit=10 // default
is_send=true|false
cURL
curl -s "http://localhost:9090/api/fingerprints/employee?from=2025-02-01T00:00:00.000Z&to=2025-02-05T23:59:59.000Z&page=1&limit=20" \
-H "Authorization: Bearer $EMPLOYEE_TOKEN"
Response (example)
{
"logs": [
{
"_id": "6925d3b4c8227c3a1972328b",
"enrollid": "121",
"event": 1,
"time": "2025-11-25T16:05:08.665Z",
"device_sn": "App",
"is_send": true,
"send_failed": false,
"forwardedAt": "2025-11-25T16:05:09.000Z"
}
],
"totalCount": 1,
"currentPage": 1,
"limit": 20,
"totalPages": 1
}
GET /api/fingerprints/mobile-logs — auth (admin)
List all mobile-app logs (device_type = "mobile_app") with filters and pagination.
Query parameters
page=1
limit=20
from=ISO8601
to=ISO8601
is_send=true|false
send_failed=true|false
cURL
curl -s "http://localhost:9090/api/fingerprints/mobile-logs?page=1&limit=20&send_failed=true" \
-H "Authorization: Bearer $TOKEN"
Response (example)
{
"success": true,
"items": [
{
"_id": "6925d3b4c8227c3a1972328b",
"enrollid": "121",
"name": "mustafa",
"event": 1,
"time": "2025-11-25T16:05:08.665Z",
"device_sn": "App",
"is_send": true,
"send_failed": false,
"forwardedAt": "2025-11-25T16:05:09.000Z",
"forwardResponse": { "success": true, "forwarded": true }
}
],
"totalCount": 1,
"currentPage": 1,
"limit": 20,
"totalPages": 1
}
Mobile fingerprints — retry forwarding failed & pending
This endpoint retries forwarding all mobile-app fingerprints that either failed to send or are still pending (is_send = false).
POST /api/fingerprints/retry-failed — auth (admin)
Request body
{}
cURL
curl -s -X POST http://localhost:9090/api/fingerprints/retry-failed \
-H "Authorization: Bearer $TOKEN" \
-H "Content-Type: application/json" \
-d '{}'
Behavior
- Selects logs where:
device_type = "mobile_app" AND
( (is_send = true AND send_failed = true) OR (is_send = false) )
- For each log:
→ Sends payload:
{ "sn": log.device_sn || "App",
"record": [ { "enrollid", "time", "event" } ] }
→ Updates:
is_send = true
send_failed = !ok
forwardResponse, forwardedAt, last_attempt_error
Response (example)
{
"success": true,
"message": "Retry finished",
"count": 5,
"successCount": 4,
"failedCount": 1,
"results": [
{ "id": "6925d3b4c8227c3a1972328b", "ok": true, "response": { "success": true, "forwarded": true } },
{ "id": "6925d3b4c8227c3a1972328c", "ok": false, "error": "Remote server did not confirm receipt" }
]
}
Contact & Notes
- The examples assume HTTP server on http://localhost:9090 and WebSocket port on ws://localhost:9091.
- Replace $TOKEN with the admin JWT returned by login, and $EMPLOYEE_TOKEN with the employee JWT.
- The Operation model is central; storing payload + response enables auditing, retries, and manual replays.
- Mobile fingerprints are stored in FingerPrintLog and can be forwarded to external HR/attendance systems.