# Anviz Local Web API

**URL:** <https://community.anviz.com/t/anviz-local-web-api/2761>\
**Category:** Integration\
**Created:** [August 6, 2026, 1:07am UTC](https://community.anviz.com/t/anviz-local-web-api/2761 "2026-08-06T01:07:53Z")\
**Posts on this page:** 3\
**Page:** 1

<div class="post-metadata">

**Author:** ![Felix\_Anviz](https://avatars.discourse-cdn.com/v4/letter/f/7c8e57/32.png) [@Felix\_Anviz](https://community.anviz.com/u/Felix_Anviz)\
**Post date:** [August 6, 2026, 1:07am UTC](https://community.anviz.com/t/anviz-local-web-api/2761/1 "2026-08-06T01:07:53Z")

</div>

Anviz Local Web API wraps the Anviz device SDK into a Docker-ready web service. Your HR, payroll, workforce management, ERP, or security platform can communicate with compatible Anviz attendance and access devices using familiar HTTPS requests and JSON responses.

For system integrators and software teams, this means less low-level SDK work, faster proof-of-concept testing, and a cleaner path from device connection to business application integration.

Docker-ready for cross-platform deployment

Deploy the service quickly across different server environments with Docker, making integration faster, more consistent, and easier to maintain.

Multi-device handling

Requests for the same device are queued, while different device IDs can be processed in parallel for smoother operations.

Real-time data with Device Client mode

Devices can actively connect to the server and upload attendance records in real time for timely data synchronization.

Developer-friendly testing

Use the built-in health check, test script, and demo page to speed up integration validation.

Ideal for

**HRMS and payroll platforms:** synchronize attendance data directly into employee time, overtime, and payroll workflows.

**Workforce management systems:** connect device records to shift, scheduling, and multi-site workforce operations.

**Security and access platforms:** combine personnel data, access settings, and remote door actions in one system.

**System integrator projects:** accelerate custom integration work for enterprise, education, construction, hospitality, and public-sector customers.

Please submit a request to download the Local Web API: [Become a Anviz Integrator Partner](https://partner.xthings.com/become-anviz-integrator?utm_source=anviz.com&utm_id=API+Download)

---

<div class="post-metadata">

**Author:** ![Felix\_Anviz](https://avatars.discourse-cdn.com/v4/letter/f/7c8e57/32.png) [@Felix\_Anviz](https://community.anviz.com/u/Felix_Anviz)\
**Post date:** [August 7, 2026, 1:08am UTC](https://community.anviz.com/t/anviz-local-web-api/2761/3 "2026-08-07T01:08:22Z")

</div>

# Anviz Local Web API User Guide

This document is for deployment and integration users. It covers Docker installation and configuration, container deployment, HTTPS/JWT configuration, API usage, and troubleshooting. The current service version enables HTTPS and JWT authentication by default.

## Project Overview

Anviz Local Web API is a Python wrapper around `libtc-b_new_sdk.so` that exposes HTTPS REST APIs. Clients send `command` and `payload` through the unified `/api/commands/execute` endpoint. The server calls the SDK to communicate with attendance devices and returns JSON.

### Core Files

- `app.py`: HTTP/HTTPS service, JWT authentication, and command dispatching.
- `sdk_wrapper.py`: SDK shared library wrapper, structure parsing, and device command implementation.
- `run_service.sh`: Startup script for local or container execution.
- `crosschex-webapi.env`: Runtime configuration file.
- `test_api.sh`: API test script with automatic login and JWT retrieval.

### Default Behavior

- Listens on `0.0.0.0:5011` by default.
- Enables HTTPS by default. Self-signed certificates are stored in `certs/`.
- Enables JWT by default. command APIs require a Bearer Token.
- Requests for the same `device_id` are queued. Different `device_id` values can be processed in parallel.

## Step 1 Docker Environment Setup

If Docker is already installed on the system, skip this chapter. The following steps use Ubuntu 22.04/24.04 as examples. In production, install Docker Engine and the Compose plugin from the official Docker APT repository. Official documentation:

- [Docker Engine on Ubuntu](https://docs.docker.com/engine/install/ubuntu/)
- [Linux post-install steps for Docker Engine](https://docs.docker.com/engine/install/linux-postinstall/)

### Install Docker Engine

```auto
# 1) Install base dependencies
sudo apt update
sudo apt install -y ca-certificates curl

# 2) Remove old packages that may conflict. Ignore errors if Docker was never installed
sudo apt remove -y docker.io docker-doc docker-compose docker-compose-v2 podman-docker containerd runc

# 3) Add the official Docker GPG key
sudo install -m 0755 -d /etc/apt/keyrings
sudo curl -fsSL https://download.docker.com/linux/ubuntu/gpg \
  -o /etc/apt/keyrings/docker.asc
sudo chmod a+r /etc/apt/keyrings/docker.asc

# 4) Add the Docker APT repository
sudo tee /etc/apt/sources.list.d/docker.sources >/dev/null <<EOF
Types: deb
URIs: https://download.docker.com/linux/ubuntu
Suites: $(. /etc/os-release && echo "${UBUNTU_CODENAME:-$VERSION_CODENAME}")
Components: stable
Architectures: $(dpkg --print-architecture)
Signed-By: /etc/apt/keyrings/docker.asc
EOF

# 5) Install Docker Engine and the Compose plugin
sudo apt update
sudo apt install -y docker-ce docker-ce-cli containerd.io docker-buildx-plugin docker-compose-plugin

# 6) Start Docker and enable it at boot
sudo systemctl enable --now docker
sudo systemctl status docker

```

### Verify Docker

```auto
sudo docker run hello-world

```

### Allow the Current User to Run Docker

```auto
sudo usermod -aG docker $USER
newgrp docker

# Verify that docker commands work without sudo
docker ps

```

If

`docker ps`

still reports insufficient permissions, log out of the current shell or restart the system and try again.

## Configuration File

`crosschex-webapi.env` is the service runtime configuration file. `run_service.sh` loads it automatically.

In production, you must change

`JWT_SECRET`

and

`AUTH_PASSWORD`

, and you should replace the HTTPS certificate with a production certificate.

| Setting | Default / Example | Description |
| --- | --- | --- |
| `HOST` | `0.0.0.0` | Web API listen address. |
| `PORT` | `5011` | Web API listen port. |
| `SDK_LIBRARY` | `/app/libtc-b_new_sdk.so` | CrossChex SDK shared library path. In containers, this path must match the image or volume mount. |
| `HTTPS_ENABLED` | `1` | Whether HTTPS is enabled. Keep it enabled in production. |
| `SSL_CERT_FILE` | `/app/certs/server.crt` | HTTPS certificate path. |
| `SSL_KEY_FILE` | `/app/certs/server.key` | HTTPS private key path. |
| `AUTH_ENABLED` | `1` | Whether JWT authentication is enabled. Keep it enabled in production. |
| `JWT_SECRET` | `openssl rand -hex 32` | JWT signing secret. Use a strong random string. |
| `JWT_EXPIRES_SECONDS` | `3600` | Token lifetime in seconds. |
| `AUTH_PASSWORD` | Custom strong password | Authentication password. Change it in production. |
| `WEBHOOK_ENABLED` | `0` | Set to 1 to enable realtime attendance record forwarding. |
| `WEBHOOK_URL` | Empty | HTTP/HTTPS endpoint that receives command 100 JSON. Leave empty to disable forwarding. |
| `WEBHOOK_TOKEN` | Empty | Optional Bearer Token. Leave empty to omit the Authorization header. |

### Generate JWT Secret

```auto
openssl rand -hex 32

```

### Generate a Self-Signed Certificate for Testing Only

```auto
mkdir -p certs
openssl req -x509 -newkey rsa:2048 -nodes \
  -keyout certs/server.key \
  -out certs/server.crt \
  -days 3650 \
  -subj "/CN=127.0.0.1"

```

For production deployment, use a certificate issued by a trusted CA. With a self-signed certificate, calls require

`curl -k`

or importing the certificate into the client trust store.

## Docker Deployment

### Recommended Directory Layout

```auto
/webapi/
├── sdk/
│ ├── certs/
│ │ ├── server.crt
│ │ └── server.key
│ ├── demo/
│ │ └── index.html
│ ├── app.py
│ ├── crosschex-webapi.env
│ ├── libtc-b_new_sdk.so
│ ├── run_http.sh
│ ├── run_service.sh
│ ├── sdk_wrapper.py
│ └── test_api.sh
├── crosschex-webapi-usage.html
└── crosschex-webapi.tar

```

### Load Image Files

```auto
docker load -i /webapi/crosschex-webapi.tar

```

### Start with docker run

```auto
# Ubuntu
docker run -it --name crosschex-webapi --network host -v /webapi/sdk:/app crosschex-webapi:latest

# Mac/Windows
docker run -it --name crosschex-webapi -p 5010:5010 -p 5011:5011 -p 8080:8080 -p 5060:5060/udp -v d:/webapi/sdk:/app crosschex-webapi:latest

```

### Check Container Runtime

```auto
docker ps --filter name=crosschex-webapi
docker logs -f crosschex-webapi
curl -k https://127.0.0.1:5011/healthz

```

## JWT Authentication

### Get Token

```auto
curl -k -X POST https://127.0.0.1:5011/api/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"password":"change-this-password"}'

```

Successful response:

```auto
{
  "code": 200,
  "token_type": "Bearer",
  "access_token": "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9...",
  "expires_in": 3600
}

```

### Call the command API

```auto
TOKEN=$(curl -k -sS -X POST https://127.0.0.1:5011/api/auth/token \
  -H 'Content-Type: application/json' \
  -d '{"password":"change-this-password"}' \
  | python3 -c 'import json,sys; print(json.load(sys.stdin)["access_token"])')

curl -k -X POST https://127.0.0.1:5011/api/commands/execute \
  -H "Content-Type: application/json" \
  -H "Authorization: Bearer $TOKEN" \
  -d '{"command":23,"payload":{}}'

```

### Authentication Errors

| HTTP Status | Scenario | Response Example |
| --- | --- | --- |
| `401` | Missing token, invalid token format, invalid signature, or expired token. | `{"code":401,"message":"Token expired."}` |

## API Usage Specification

### Health Check

The health check does not require JWT.

```auto
GET /healthz

```

```auto
curl -k https://127.0.0.1:5011/healthUnified Command Endpoint

```

```auto
POST /api/commands/execute
Content-Type: application/json
Authorization: Bearer <token>

{
  "command": 23,
  "payload": {}
}

```

All business commands use `command` to identify the operation and `payload` to carry command parameters.

### Common Response Structure

```auto
{
  "code": 200,
  "command": 23,
  "data": { ... },
  "records": [...],
  "count": 1
}

```

Not every API returns `records` and `count`. When there are no records, some APIs only return `data.totalcnt=0`.

### Common Business Error Codes

| code | HTTP Status | Description |
| --- | --- | --- |
| `400` | Bad Request | Invalid request JSON, missing parameters, or invalid parameter range. |
| `401` | Unauthorized | Authentication failed. |
| `404` | Not Found | Device not connected, API not found, or no event was received while waiting. |
| `502` | Bad Gateway | SDK call failed immediately. |
| `504` | Gateway Timeout | Timed out waiting for the device response. |

## Using the Web API Demo

### Start the demo HTTP server

```auto
docker exec -it crosschex-webapi /app/run_http.sh

```

### Open the Web API Demo page

- [CrossChex Web API Demo](http://127.0.0.1:8080)

When opening the demo page for the first time, click

`Open healthz`

first to remove browser network blocking. Then enter the correct API Base URL and password. The default password is CrossChex, but use the actual configured

`AUTH_PASSWORD`

. **strong text**

## Troubleshooting

| Symptom | Cause | Resolution |
| --- | --- | --- |
| `AUTH_ENABLED=1 but JWT_SECRET is empty` | `crosschex-webapi.env` was not loaded or `JWT_SECRET` is not configured. | Confirm that `run_service.sh` loads the env file, or set `ENV_FILE`. Configure a strong random `JWT_SECRET`. |
| `Missing Authorization Bearer token` | The command API was called without JWT. | Call `/api/auth/token` first, then include `Authorization: Bearer <token>`. |
| `Token expired` | JWT exceeded `JWT_EXPIRES_SECONDS`. | Log in again to get a new token. |
| `SSL cert file not found` | Certificate path is wrong or `certs` is not mounted in the container. | Check `SSL_CERT_FILE`, `SSL_KEY_FILE`, and volume mounts. |
| `Timed out while waiting for device response` | Device does not respond, network is unreachable, port is unreachable, or the event does not match. | Check device IP, port 5010, container host network, device connection state, and SDK logs. |
| UDP search cannot find devices | Container network isolation restricts UDP broadcast. | Use `--network host` or `network_mode: host`. |
| HTTPS curl certificate error | A self-signed certificate is used. | Use `-k` during testing. Use a trusted certificate in production. |

### View Logs

````auto
# Docker run
docker logs -f crosschex-webapi

# With systemd deployment
journalctl -u crosschex-webapi -f
``` **strong text**

````

---

<div class="post-metadata">

**Author:** ![Felix\_Anviz](https://avatars.discourse-cdn.com/v4/letter/f/7c8e57/32.png) [@Felix\_Anviz](https://community.anviz.com/u/Felix_Anviz)\
**Post date:** [August 7, 2026, 1:19am UTC](https://community.anviz.com/t/anviz-local-web-api/2761/4 "2026-08-07T01:19:43Z")

</div>

## API Command List V1.0

| command | Name | Main payload parameters | Description |
| --- | --- | --- | --- |
| 1 | Connect Device | `device_id`, `device_ip`, `device_port` | Call the SDK to connect to a device and return device ID, type, version, IP, and dev\_idx. |
| 2 | Read New Records | `device_id` | Read record status first. If `NewRecNum=0`, return `totalcnt=0` immediately. |
| 3 | Disconnect Device | `device_id` | Disconnect a connected device. |
| 4 | Read All Records | `device_id` | Read record status first. If `TotalRecNum=0`, return `totalcnt=0` immediately. |
| 5 | Read Record Status | `device_id` | Return employee, fingerprint, password, card, total record, and new record counts. |
| 6 | Clear Records | `device_id` | Delete or clear device records. |
| 7 | Read Person Info | `device_id` | Read record status first. If `EmployeeNum=0`, return `totalcnt=0` immediately. |
| 8 | Add/Modify Person | `device_id`, `userid`, `password`, `card_id`, `username`, etc. | Write basic person information. |
| 9 | Delete Person | `device_id`, `userid`, `operation` | Delete a person or person-related data. |
| 10 | Read Device Time | `device_id` | Return the current device time. |
| 11 | Set Device Time | `device_id`, `year`, `month`, `day`, `hour`, `minute`, `second` | Set the device time. |
| 12 | Initialize User Area | `device_id` | Clear user-related areas. |
| 13 | Initialize System | `device_id` | Initialize the device system. This is a high-risk operation. |
| 14 | Force Unlock | `device_id` | Trigger device force unlock. |
| 15 | Read SN | `device_id` | Read the device serial number. |
| 16 | Download Fingerprint Template | `device_id`, `userid`, `templateid` | Read a user fingerprint template. |
| 17 | Upload Fingerprint Template | `device_id`, `userid`, `templateid`, `template`, `template_len` | Write a user fingerprint template. |
| 18 | Download Face Image Template | `device_id`, `userid` | Read a face image template. |
| 19 | Upload Face Image Template | `device_id`, `userid`, `template` | Write a face image template. |
| 20 | Enroll Fingerprint Online | `device_id`, `userid`, `templateid` | Trigger online fingerprint enrollment on the device. |
| 21 | Enroll Face Online | `device_id`, `userid` | Trigger online face image enrollment on the device. |
| 22 | Read Records by User and Time | `device_id`, `userid`, `start_date`, `end_date` | Read the matching record count first and return immediately if it is 0. |
| 23 | List Connected Devices | None | Return the list of connected devices in the current service. `records` is always an array. |
| 24 | Read Period Settings | `device_id`, `timeid` | `timeid` range is 1..32. Returns start1/end1 through start7/end7. |
| 25 | Set Period Settings | `device_id`, `timeid`, `start1`..`end7` | Time format is `HH:mm`. |
| 26 | Read Group Settings | `device_id`, `teamid` | `teamid` must be in the range 2..16. Returns timeid1..timeid4. |
| 27 | Set Group Settings | `device_id`, `teamid`, `timeid1`..`timeid4` | `teamid` must be in the range 2..16. |
| 28 | Read Attendance Status | `device_id` | Return `fp_len` and status1..status8. |
| 29 | Set Attendance Status | `device_id`, `status1`..`status8` | The status field length depends on the device type. |
| 30 | Search Devices | None | Search LAN devices over UDP and return IP, MAC, port, version, and related information. |

### Request and Response JSON Examples

The following examples show successful responses. Actual values may vary by device model, firmware version, and data content. Field structure follows the current API implementation.

### command=1 Connect Device

#### Request JSON

```auto
{
  "command": 1,
  "payload": {
    "device_id": 1,
    "device_ip": "192.168.0.144",
    "device_port": 5010
  }
}

```

#### Response JSON

```auto
{
  "code": 200,
  "command": 1,
  "data": {
    "device_id": 1,
    "device_type": "FDEEP3M",
    "device_typeflag": 45154820,
    "device_ip": "192.168.0.144:5010",
    "device_version": "03.74.D6",
    "device_idx": 1
  }
}

```

### command=2 Read New Records

#### Request JSON

```auto
{
  "command": 2,
  "payload": {
    "device_id": 1
  }
}

```

#### Response JSON

```auto
{
  "code": 200,
  "command": 2,
  "data": {
    "device_id": 1,
    "totalcnt": 1
  },
  "records": [
    {
      "userid": 1,
      "checktime": "2026-07-27 09:30:00",
      "backid": 16,
      "rectype": 128, //highest bit 1 means door opened, for example 128: opened+IN, 129: opened+OUT, 0: IN, 1: OUT
      "curidx": 1
    }
  ],
  "count": 1
}

```
