Cloud API (App → Server)¶
All endpoints below are called by the Novabot Flutter app.
Original base URL: https://app.lfibot.com → local http://<server-ip>:3000
All authenticated endpoints require a JWT Authorization header.
See Authentication for details.
nova-user: AppUser¶
POST /api/nova-user/appUser/login¶
Login with email and password.
Auth: None
{
"email": "[email protected]",
"password": "AES-encrypted-password"
}
Password Encryption
Password is AES-128-CBC encrypted: key/IV = 1234123412ABCDEF, output base64.
{
"appUserId": "uuid-string",
"email": "[email protected]",
"phone": null,
"firstName": null,
"lastName": null,
"accessToken": "jwt-token",
"newUserFlag": 0,
"country": null,
"city": null,
"address": null,
"coordinates": null
}
POST /api/nova-user/appUser/regist¶
Register a new user account.
Auth: None
{
"email": "[email protected]",
"password": "AES-encrypted-password",
"username": "optional-name"
}
{
"appUserId": "uuid-string",
"email": "[email protected]",
"token": "jwt-token"
}
POST /api/nova-user/appUser/loginOut¶
Logout current session.
Auth: JWT
GET /api/nova-user/appUser/appUserInfo¶
Get current user profile.
Auth: JWT
| Query Param | Type | Description |
|---|---|---|
email |
string | Optional email filter |
{
"appUserId": "uuid",
"email": "[email protected]",
"username": "name",
"machineToken": "FCM-push-token"
}
POST /api/nova-user/appUser/appUserInfoUpdate¶
Update user profile.
Auth: JWT
POST /api/nova-user/appUser/appUserPwdUpdate¶
Change password.
Auth: JWT
POST /api/nova-user/appUser/deleteAccount¶
Delete user account permanently.
Auth: JWT
POST /api/nova-user/appUser/updateAppUserMachineToken¶
Update FCM push notification token.
Auth: JWT
machineToken is NOT for MQTT
This is a Firebase Cloud Messaging token for push notifications, not related to MQTT authentication.
nova-user: Validate¶
POST /api/nova-user/validate/sendAppRegistEmailCode¶
Send registration verification email.
Auth: None
{
"email": "[email protected]"
}
POST /api/nova-user/validate/validAppRegistEmailCode¶
Validate registration email code.
Auth: None
{
"email": "[email protected]",
"code": "123456"
}
POST /api/nova-user/validate/sendAppResetPwdEmailCode¶
Send password reset email.
Auth: None
{
"email": "[email protected]"
}
POST /api/nova-user/validate/verifyAndResetAppPwd¶
Verify code and reset password.
Auth: None
{
"email": "[email protected]",
"code": "123456",
"newPassword": "AES-encrypted"
}
nova-user: Equipment¶
POST /api/nova-user/equipment/userEquipmentList¶
List all bound equipment for user.
Auth: JWT
{
"pageNo": 1,
"pageSize": 100,
"totalSize": 2,
"totalPage": 1,
"pageList": [
{
"equipmentId": 755,
"email": "",
"deviceType": "charger",
"sn": "LFIC1230700XXX",
"equipmentCode": "LFIC1230700XXX",
"equipmentName": "LFIC1230700XXX",
"equipmentType": "LFIC1",
"userId": 0,
"sysVersion": "v0.3.6",
"period": "2029-02-22 00:00:00",
"status": 1,
"online": true,
"activationTime": "2026-02-21 18:32:12",
"macAddress": "48:27:E2:1B:A4:0A",
"chargerAddress": 718,
"chargerChannel": 16,
"account": "<mqtt-username>",
"password": "<mqtt-password>",
"videoTutorial": null,
"model": null,
"wifiName": null,
"wifiPassword": null
}
]
}
App parses specific field names
The app's EquipmentEntity.fromJson expects exactly these fields:
chargerSn, chargerVersion, equipmentId, equipmentNickName, equipmentTypeH,
macAddress, mowerVersion, online, status, chargerAddress, chargerChannel, userId
POST /api/nova-user/equipment/getEquipmentBySN¶
Get equipment details by serial number.
Auth: JWT
{
"equipmentId": 755,
"email": "",
"deviceType": "charger",
"sn": "LFIC1230700XXX",
"equipmentCode": "LFIC1230700XXX",
"equipmentName": "LFIC1230700XXX",
"equipmentType": "LFIC1",
"userId": 0,
"sysVersion": "v0.3.6",
"period": "2029-02-22 00:00:00",
"status": 1,
"activationTime": "2026-02-21 18:32:12",
"importTime": "2023-08-23 18:22:48",
"batteryState": null,
"macAddress": "48:27:E2:1B:A4:0A",
"chargerAddress": 718,
"chargerChannel": 16,
"account": "<mqtt-username>",
"password": "<mqtt-password>"
}
{
"equipmentId": 756,
"deviceType": "mower",
"sn": "LFIN2230700XXX",
"macAddress": "50:41:1C:39:BD:C1",
"chargerAddress": null,
"chargerChannel": null,
"account": null,
"password": null
}
MAC address = BLE MAC
The cloud returns the BLE MAC (not WiFi STA MAC). The app matches this against BLE manufacturer data during scanning.
POST /api/nova-user/equipment/bindingEquipment¶
Bind equipment to user account.
Auth: JWT
{
"mowerSn": "LFIN2230700XXX",
"chargerSn": "LFIC1230700XXX",
"equipmentTypeH": "Novabot",
"userCustomDeviceName": "My Mower",
"chargerChannel": 15
}
Note
chargerChannel comes from the set_lora_info_respond value during BLE provisioning.
POST /api/nova-user/equipment/unboundEquipment¶
Unbind equipment from user.
Auth: JWT
POST /api/nova-user/equipment/updateEquipmentNickName¶
Rename equipment.
Auth: JWT
POST /api/nova-user/equipment/updateEquipmentVersion¶
Update firmware version record.
Auth: JWT
nova-user: OTA Upgrade¶
GET /api/nova-user/otaUpgrade/checkOtaNewVersion¶
Check for new firmware version. Returns the latest available firmware for the given equipment type.
Auth: JWT
| Query Param | Type | Example | Description |
|---|---|---|---|
version |
string | v0.0.0 |
Current firmware version (use v0.0.0 to always get latest) |
upgradeType |
string | serviceUpgrade |
Upgrade type |
equipmentType |
string | LFIN2 |
First 5 chars of SN |
sn |
string | LFIN2230700238 |
Device serial number (optional, ignored by cloud) |
{
"version": "v5.7.1",
"upgradeType": "serviceUpgrade",
"md5": "<md5-checksum>",
"downloadUrl": "https://<oss-host>/novabot-file/<firmware-file>.deb",
"upgradeFlag": 0,
"environment": "trial",
"dependenceSystemVersionList": null
}
Cloud ignores SN parameter
The cloud OTA API returns the same firmware version for ALL serial numbers of a given equipment type. The sn parameter is ignored — there is no per-device versioning via this endpoint. Firmware v6.0.3 (seen pushed to select users) was likely delivered via direct MQTT ota_upgrade_cmd, not through this API.
Known firmware versions per equipment type:
| Equipment Type | Version | Description |
|---|---|---|
LFIN2 |
v5.7.1 | Mower (Debian/ROS 2, 35MB) |
LFIN1 |
v5.7.1 | Mower (older model) |
LFIC1 |
v0.3.6 | Charger (ESP32-S3, 1.4MB) |
LFIC2 |
v0.3.6 | Charger (variant) |
LFIN3, LFIC3, LFI01, N1000, N2000 |
v0.3.6 | Various equipment types |
nova-data: Cut Grass Plans¶
GET /api/nova-data/appManage/queryCutGrassPlan¶
Get all mowing schedules for equipment.
Auth: JWT
| Query Param | Type | Description |
|---|---|---|
equipmentId |
string | Equipment UUID |
[
{
"planId": "uuid",
"equipmentId": "uuid",
"startTime": "08:00",
"endTime": "12:00",
"weekday": [1, 3, 5],
"repeat": true,
"repeatCount": 0,
"repeatType": "weekly",
"workTime": 240,
"workArea": ["map0"],
"workDay": ["Mon", "Wed", "Fri"]
}
]
POST /api/nova-data/appManage/saveCutGrassPlan¶
Create a new mowing schedule.
Auth: JWT
{
"equipmentId": "uuid",
"startTime": "08:00",
"endTime": "12:00",
"weekday": [1, 3, 5],
"repeat": true,
"repeatCount": 0,
"repeatType": "weekly",
"workTime": 240,
"workArea": ["map0"],
"workDay": ["Mon", "Wed", "Fri"]
}
POST /api/nova-data/appManage/updateCutGrassPlan¶
Update an existing schedule.
Auth: JWT
POST /api/nova-data/appManage/deleteCutGrassPlan¶
Delete a schedule.
Auth: JWT
POST /api/nova-data/appManage/queryNewVersion¶
Check for new app version.
Auth: None
GET /api/nova-data/cutGrassPlan/queryRecentCutGrassPlan¶
Get most recent schedule.
Auth: JWT
| Query Param | Type | Description |
|---|---|---|
equipmentId |
string | Equipment UUID |
nova-file-server: Maps¶
GET /api/nova-file-server/map/queryEquipmentMap¶
Get all maps for equipment.
Auth: JWT
| Query Param | Type | Description |
|---|---|---|
sn |
string | Serial number |
[
{
"mapId": "uuid",
"mowerSn": "LFIN2230700XXX",
"mapName": "Garden",
"mapArea": [[52.141, 6.231], [52.142, 6.232]],
"mapMaxMin": null,
"fileSize": 1024,
"createdAt": "2026-02-21T18:32:12Z",
"updatedAt": "2026-02-21T18:32:12Z"
}
]
POST /api/nova-file-server/map/fragmentUploadEquipmentMap¶
Upload map data in chunks (from app).
Auth: JWT
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
sn |
string | Serial number |
uploadId |
string | Upload session ID |
fileSize |
number | Total file size |
chunkIndex |
number | Current chunk index |
chunksTotal |
number | Total number of chunks |
mapName |
string | Map name |
mapArea |
string | JSON polygon coordinates |
mapMaxMin |
string | Bounding box |
file |
binary | Chunk data |
{
"mapId": "uuid",
"uploadId": "upload-id",
"complete": true,
"chunksReceived": 5,
"chunksTotal": 5
}
POST /api/nova-file-server/map/updateEquipmentMapAlias¶
Rename a map.
Auth: JWT
nova-file-server: Logs¶
POST /api/nova-file-server/log/uploadAppOperateLog¶
Upload app operation logs.
Auth: JWT
Content-Type: multipart/form-data
| Field | Type | Description |
|---|---|---|
file |
binary | Log file |
novabot-message¶
GET /api/novabot-message/message/queryRobotMsgPageByUserId¶
Get robot messages with pagination.
Auth: JWT
| Query Param | Type | Description |
|---|---|---|
page |
number | Page number |
limit |
number | Items per page |
{
"total": 10,
"page": 1,
"limit": 20,
"list": [
{
"messageId": "uuid",
"type": "error",
"content": "Blade motor stalled",
"createdAt": "2026-02-21T18:32:12Z",
"read": false
}
]
}
POST /api/novabot-message/message/queryMsgMenuByUserId¶
Get unread message counts.
Auth: JWT
POST /api/novabot-message/message/updateMsgByUserId¶
Mark messages as read.
Auth: JWT
POST /api/novabot-message/message/deleteMsgByUserId¶
Delete messages.
Auth: JWT
GET /api/novabot-message/message/queryCutGrassRecordPageByUserId¶
Get mowing work records with pagination.
Auth: JWT
| Query Param | Type | Description |
|---|---|---|
page |
number | Page number |
limit |
number | Items per page |
nova-network¶
POST /api/nova-network/network/connection¶
Connectivity check. Called by both the app (~5 second interval) and mower firmware.
Auth: None