Skip to content

API Reference

Overview

The application exposes a small set of authenticated JSON and multipart endpoints under GET /, /live-identify, /ui, and /api/v1/*.

Unless noted otherwise, authenticated endpoints accept the custom access token in the Authorization header. The implementation accepts either:

  • Authorization: Bearer <token>
  • Authorization: <token>

Endpoint Summary

Method URL Auth Notes
GET /api/v1/health No Service health
POST /api/v1/auth/login No Login and issue access token
GET /api/v1/auth/me Yes Current user info
GET /api/v1/auth/users Yes List users
POST /api/v1/auth/users Yes Create user
DELETE /api/v1/auth/users/{username} Yes Delete user
PATCH /api/v1/auth/users/{username}/password Yes Change password
GET /api/v1/auth/audit Yes Get audit logs (superadmin/admin only)
DELETE /api/v1/auth/audit Yes Clear audit logs (superadmin only)
POST /api/v1/biometrics/enroll/upload Yes Enroll from photo
DELETE /api/v1/biometrics/enroll/{person_id} Yes Delete enrollment
GET /api/v1/biometrics/enrollments Yes List all biometric enrollments
GET /api/v1/biometrics/enrollments/{person_id} Yes Get details of a specific enrollment
PATCH /api/v1/biometrics/enrollments/{person_id}/status Yes Toggle activation status of enrollment
POST /api/v1/biometrics/identify/upload Yes Identify from photo
POST /api/v1/biometrics/identify/live-video/upload Yes Live-video identify
POST /api/v1/biometrics/recognize/live-video/upload Yes Same behavior as live-video identify
POST /api/v1/biometrics/verify/upload Yes Verify a claimed person_id
POST /api/v1/biometrics/enroll Yes Hidden alias for enrollment upload
POST /api/v1/biometrics/identify Yes Hidden alias for live-video identify
GET / No Root discovery endpoint
GET /live-identify No 307 redirect to /ui/index.html

Common Error Conventions

  • 400 Bad Request: invalid image, invalid frame sequence, spoof detected, or validation failure.
  • 401 Unauthorized: missing or invalid token, or bad credentials on login.
  • 403 Forbidden: role not allowed for the requested action.
  • 404 Not Found: only used by password change when the target account does not exist.
  • 409 Conflict: duplicate enrollment or duplicate username.
  • 422 Unprocessable Entity: request body validation failure or required field missing.
  • 429 Too Many Requests: API rate limit exceeded.
  • 500 Internal Server Error: unexpected runtime failure.

Authentication

POST /api/v1/auth/login

Authenticate a user and issue a signed access token.

Request

  • Method: POST
  • Content-Type: application/json

Body parameters

Name Type Required Description
username string Yes Account username
password string Yes Account password

Example request

curl -X POST "https://YOUR_HOST/api/v1/auth/login" \
  -H "Content-Type: application/json" \
  -d '{"username":"superadmin","password":"superadmin"}'

Success response 200

{
  "access_token": "<Your Token>",
  "token_type": "bearer",
  "expires_at": "2026-06-03T12:34:56Z",
  "role": "superadmin",
  "subject": "superadmin"
}

Error responses

  • 401: Invalid username or password.
  • 422: JSON validation failure

GET /api/v1/auth/me

Return the authenticated subject and role.

Example request

curl -H "Authorization: Bearer $TOKEN" \
  "https://YOUR_HOST/api/v1/auth/me"

Success response 200

{
  "subject": "superadmin",
  "role": "superadmin"
}

Error responses

  • 401: missing, empty, invalid, or expired token

GET /api/v1/auth/users

List all user accounts. Allowed roles: superadmin, admin.

Example request

curl -H "Authorization: Bearer $TOKEN" \
  "https://YOUR_HOST/api/v1/auth/users"

Success response 200

[
  {
    "username": "superadmin",
    "role": "superadmin",
    "created_by": "system",
    "created_at": "2026-06-03T09:00:00+00:00",
    "updated_at": "2026-06-03T09:00:00+00:00"
  }
]

Error responses

  • 401: invalid token
  • 403: role not permitted

POST /api/v1/auth/users

Create a user account. Allowed roles: superadmin, admin.

Body parameters

Name Type Required Description
username string Yes New account username
password string Yes New account password, minimum 8 characters
role string Yes One of admin or viewer

Example request

curl -X POST "https://YOUR_HOST/api/v1/auth/users" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"username":"viewer01","password":"viewerpass1","role":"viewer"}'

Success response 200

{
  "username": "viewer01",
  "role": "viewer",
  "created_by": "superadmin",
  "created_at": "2026-06-03T09:15:00+00:00",
  "updated_at": "2026-06-03T09:15:00+00:00"
}

Error responses

  • 401: invalid token
  • 403: role not permitted or superadmin creation blocked
  • 409: username already exists
  • 422: validation failure or empty username/password

DELETE /api/v1/auth/users/{username}

Delete an account. Allowed roles: superadmin, admin.

Important behavior:

  • deleting your own account is forbidden
  • deleting a missing account returns deleted: false rather than a 404
  • superadmin accounts cannot be deleted through the API

Example request

curl -X DELETE "https://YOUR_HOST/api/v1/auth/users/viewer01" \
  -H "Authorization: Bearer $TOKEN"

Success response 200

{
  "username": "viewer01",
  "deleted": true
}

Missing user response 200

{
  "username": "missing-user",
  "deleted": false
}

Error responses

  • 401: invalid token
  • 403: self-delete, role mismatch, or superadmin protection

PATCH /api/v1/auth/users/{username}/password

Change a password for yourself or, subject to role rules, another account.

Body parameters

Name Type Required Description
new_password string Yes New password, minimum 8 characters
current_password string Conditional Required when changing your own password

Example request

curl -X PATCH "https://YOUR_HOST/api/v1/auth/users/viewer01/password" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"new_password":"newpass123","current_password":"viewerpass1"}'

Success response 200

{
  "username": "viewer01",
  "password_changed": true,
  "changed_by": "viewer01",
  "updated_at": "2026-06-03T09:20:00+00:00"
}

Error responses

  • 401: invalid token
  • 403: role mismatch or incorrect current password
  • 404: user account not found
  • 422: missing or empty username/password/current_password where required
  • 500: password change succeeded but the account could not be reloaded

Audit

GET /api/v1/auth/audit

Retrieve all audit log events in descending chronological order. Allowed roles: superadmin, admin.

Example request

curl -H "Authorization: Bearer $TOKEN" \
  "https://YOUR_HOST/api/v1/auth/audit"

Success response 200

[
  {
    "timestamp": "2026-06-19T05:57:55.297133Z",
    "event_type": "login",
    "actor": "superadmin",
    "resource": "superadmin",
    "outcome": "failure",
    "details": {
      "reason": "Invalid username or password."
    }
  },
  {
    "timestamp": "2026-06-19T05:57:44.668796Z",
    "event_type": "clear-audit-logs",
    "actor": "superadmin",
    "resource": "audit_events",
    "outcome": "success",
    "details": {}
  }
]

Error responses

  • 401: invalid token
  • 403: role not permitted (e.g. viewer)

DELETE /api/v1/auth/audit

Clear all persistent audit records and log the clear action. Allowed roles: superadmin only.

Example request

curl -X DELETE -H "Authorization: Bearer $TOKEN" \
  "https://YOUR_HOST/api/v1/auth/audit"

Success response 200

{
  "status": "success",
  "message": "Audit logs cleared successfully."
}

Error responses

  • 401: invalid token
  • 403: role not permitted (e.g. admin, viewer)

Biometrics

POST /api/v1/biometrics/enroll/upload

Enroll a person from a single face photo.

Request

  • Method: POST
  • Content-Type: multipart/form-data
  • Query string: force_update optional boolean, default false

Form fields

Name Type Required Description
person_id string Yes Unique identifier
name string Yes Display name
photo file Yes JPG or PNG face photo

Example request

curl -X POST "https://YOUR_HOST/api/v1/biometrics/enroll/upload?force_update=false" \
  -H "Authorization: Bearer $TOKEN" \
  -F "person_id=EMP001" \
  -F "name=Example User" \
  -F "photo=@face.jpg"

Success response 200

{
  "status": "enrolled",
  "person_id": "EMP001",
  "name": "Example User",
  "enrolled_at": "2026-06-03T09:30:00+00:00"
}

Error responses

  • 400: unsupported file type, decode failure, no face, multiple faces, or model error
  • 401: invalid token
  • 403: role not permitted
  • 409: duplicate person_id when force_update=false
  • 422: missing required form fields

DELETE /api/v1/biometrics/enroll/{person_id}

Delete a biometric enrollment.

Example request

curl -X DELETE "https://YOUR_HOST/api/v1/biometrics/enroll/EMP001" \
  -H "Authorization: Bearer $TOKEN"

Success response 200

{
  "person_id": "EMP001",
  "deleted": true
}

Not found behavior

{
  "person_id": "EMP001",
  "deleted": false
}

Error responses

  • 401: invalid token
  • 403: role not permitted

GET /api/v1/biometrics/enrollments

List all biometric enrollments in the database. Allowed roles: superadmin, admin.

Example request

curl -H "Authorization: Bearer $TOKEN" \
  "https://YOUR_HOST/api/v1/biometrics/enrollments"

Success response 200

[
  {
    "person_id": "EMP001",
    "name": "Example User",
    "enrolled_at": "2026-06-03T09:30:00+00:00",
    "is_active": true,
    "employee_id": "emp001",
    "email": "user@example.com",
    "phone": "+1234567890",
    "department": "Engineering",
    "designation": "Software Developer",
    "location": "HQ",
    "manager_name": "Manager Name",
    "tags": ["developer", "HQ"],
    "notes": "Some notes about user",
    "last_updated_at": "2026-06-03T09:30:00+00:00"
  }
]

Error responses

  • 401: invalid token
  • 403: role not permitted (e.g. viewer)

GET /api/v1/biometrics/enrollments/{person_id}

Retrieve full biometric enrollment details for a specific person_id. Allowed roles: superadmin, admin.

Example request

curl -H "Authorization: Bearer $TOKEN" \
  "https://YOUR_HOST/api/v1/biometrics/enrollments/EMP001"

Success response 200

{
  "person_id": "EMP001",
  "name": "Example User",
  "enrolled_at": "2026-06-03T09:30:00+00:00",
  "is_active": true,
  "employee_id": "emp001",
  "email": "user@example.com",
  "phone": "+1234567890",
  "department": "Engineering",
  "designation": "Software Developer",
  "location": "HQ",
  "manager_name": "Manager Name",
  "tags": ["developer", "HQ"],
  "notes": "Some notes about user",
  "last_updated_at": "2026-06-03T09:30:00+00:00"
}

Error responses

  • 401: invalid token
  • 403: role not permitted (e.g. viewer)
  • 404: person not found

PATCH /api/v1/biometrics/enrollments/{person_id}/status

Toggle the activation status of a biometric enrollment. Deactivating a profile excludes it from face match identification/verification operations without deleting the database records. Allowed roles: superadmin, admin.

Request

  • Method: PATCH
  • Content-Type: application/json

Body parameters

Name Type Required Description
is_active boolean Yes Target activation status (set true for active, false for inactive)

Example request

curl -X PATCH "https://YOUR_HOST/api/v1/biometrics/enrollments/EMP001/status" \
  -H "Authorization: Bearer $TOKEN" \
  -H "Content-Type: application/json" \
  -d '{"is_active": false}'

Success response 200

{
  "person_id": "EMP001",
  "is_active": false
}

Error responses

  • 400: missing or invalid is_active field
  • 401: invalid token
  • 403: role not permitted (e.g. viewer)
  • 404: person not found

POST /api/v1/biometrics/identify/upload

Identify a person from a single face photo.

Request

  • Method: POST
  • Content-Type: multipart/form-data

Form fields

Name Type Required Description
photo file Yes JPG or PNG face photo

Example request

curl -X POST "https://YOUR_HOST/api/v1/biometrics/identify/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -F "photo=@probe.jpg"

Success response 200

{
  "matched": true,
  "person_id": "EMP001",
  "name": "Example User",
  "confidence": 0.7821,
  "match_threshold": 0.45,
  "candidates_checked": 12,
  "capture_mode": "photo"
}

If no enrollments exist, the response is still 200 and looks like this:

{
  "matched": false,
  "person_id": null,
  "name": "Unknown",
  "confidence": 0.0,
  "match_threshold": 0.45,
  "candidates_checked": 0,
  "capture_mode": "photo"
}

Error responses

  • 400: unsupported file type, decode failure, no face, multiple faces, or no face detected in the uploaded image
  • 401: invalid token
  • 403: role not permitted
  • 422: missing file

POST /api/v1/biometrics/identify/live-video/upload

Identify a person from a live frame sequence. This endpoint has the same behavior as /api/v1/biometrics/recognize/live-video/upload.

Request

  • Method: POST
  • Content-Type: multipart/form-data

Form fields

Name Type Required Description
frames repeated string fields Yes Base64-encoded JPEG frames, typically 10 to 30 items

The UI captures 20 frames at about 5 fps.

Example request

curl -X POST "https://YOUR_HOST/api/v1/biometrics/identify/live-video/upload" \
  -H "Authorization: Bearer $TOKEN" \
  --form-string "frames=$(base64 -w0 frame_01.jpg)" \
  --form-string "frames=$(base64 -w0 frame_02.jpg)"

Success response 200

{
  "verdict": "live",
  "matched": true,
  "person_id": "EMP001",
  "name": "Example User",
  "confidence": 0.8012,
  "liveness": {
    "blink_detected": true,
    "micro_movement_detected": true
  }
}

If no enrollments exist, the endpoint still returns 200:

{
  "verdict": "live",
  "matched": false,
  "person_id": null,
  "name": "Unknown",
  "confidence": 0.0,
  "liveness": {
    "blink_detected": true,
    "micro_movement_detected": true
  },
  "message": "No enrolled persons in database."
}

If the capture fails liveness, the server returns 400 with a structured detail object:

{
  "detail": {
    "verdict": "spoof_detected",
    "reason": "no blink detected -- please blink naturally during capture, no face movement detected -- please hold phone naturally",
    "liveness": {
      "blink_detected": false,
      "micro_movement_detected": false
    }
  }
}

Error responses

  • 400: too few frames, no face detected in the captured sequence, or spoof detected
  • 401: invalid token
  • 403: role not permitted
  • 422: missing frames

POST /api/v1/biometrics/recognize/live-video/upload

Same behavior, payload, and responses as /api/v1/biometrics/identify/live-video/upload.

POST /api/v1/biometrics/verify/upload

Verify a face against a known person_id.

Request

  • Method: POST
  • Content-Type: multipart/form-data

Form fields

Name Type Required Description
person_id string Yes Known enrolled person ID
photo file Yes JPG or PNG face photo

Example request

curl -X POST "https://YOUR_HOST/api/v1/biometrics/verify/upload" \
  -H "Authorization: Bearer $TOKEN" \
  -F "person_id=EMP001" \
  -F "photo=@probe.jpg"

Success response 200

{
  "person_id": "EMP001",
  "enrolled": true,
  "matched": true,
  "name": "Example User",
  "confidence": 0.7815,
  "match_threshold": 0.45,
  "capture_mode": "photo",
  "message": "person_id is enrolled and matched."
}

If the person_id is not enrolled, the endpoint still returns 200:

{
  "person_id": "EMP999",
  "enrolled": false,
  "matched": false,
  "confidence": 0.0,
  "match_threshold": 0.45,
  "capture_mode": "photo",
  "message": "person_id is not enrolled."
}

Error responses

  • 400: unsupported file type, decode failure, no face, multiple faces, or model error
  • 401: invalid token
  • 403: role not permitted
  • 422: missing required form fields

Hidden aliases

The following routes are implemented but excluded from the OpenAPI schema:

  • POST /api/v1/biometrics/enroll
  • POST /api/v1/biometrics/identify

Each is an alias of the corresponding upload endpoint and uses the same request and response behavior.

Utility Routes

GET /api/v1/health

Return the service health response.

Success response 200

{
  "status": "ok",
  "service": "PowerMind VisionID",
  "version": "1.1.0"
}

GET /

Return a discovery payload with the service name, version, and key endpoint paths.

Success response 200

{
  "service": "PowerMind VisionID",
  "version": "1.1.0",
  "endpoints": {
    "login": "/api/v1/auth/login",
    "current_user": "/api/v1/auth/me",
    "enroll": "/api/v1/biometrics/enroll/upload",
    "delete_enrollment": "/api/v1/biometrics/enroll/{person_id}",
    "identify_photo": "/api/v1/biometrics/identify/upload",
    "identify_live_video": "/api/v1/biometrics/identify/live-video/upload",
    "recognize_live_video": "/api/v1/biometrics/recognize/live-video/upload",
    "verify_enrollment": "/api/v1/biometrics/verify/upload",
    "health": "/api/v1/health",
    "metrics": "/metrics",
    "ui": "/ui/index.html"
  }
}

GET /live-identify

Redirect to the UI landing page.

Response

  • 307 Temporary Redirect
  • Location: /ui/index.html

Static UI

The application also serves the browser UI under /ui. The main entry point is /ui/index.html.