Repository navigation
Reference Fleet
Mowers, sites, groups, linked cloud accounts, base stations and commands.
Base path /api/v1/fleet behind the gateway. Authentication, rate limits and the error format are the same for every service: see Scripting MowDeck. Rendered from apps/web/openapi/fleet.json (OpenAPI 3.1), which you can also load into any OpenAPI tool.
List Base Stations
The RTK base stations of the caller's account with their linked mowers (can_view).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json BaseStationList
|
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
Register Base Station
Register an RTK base station (can_manage_mowers): a device of a linked account that its device list marks rtk_base, or (source simulated) the simulator's base station. 409 base-station-already-registered when that physical base station is registered already (in this or another account, which is not named).
Request body (required): application/json BaseStationIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json BaseStationOut
|
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
| 409 |
base-station-already-registered, or the account's limit. |
no body |
| 422 | Unknown linked account or device, or not an RTK base station. | no body |
Get Base Station
One base station (can_view).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
base_station_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json BaseStationOut
|
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Update Base Station
Rename the base station (can_manage_mowers).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
base_station_id |
path | string (uuid) | yes |
Request body (required): application/json BaseStationPatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json BaseStationOut
|
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Base Station
Remove the base station (can_manage_mowers); its mowers lose the link.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
base_station_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Check Base Station Firmware
Ask the vendor for the base station's firmware through a linked mower (can_view); the answer also lands in the linked mowers' state (MowerState.base_station).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
base_station_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json FirmwareInfo
|
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
| 409 |
base-station-not-linked: no mower is linked to it. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | No Device-Gateway holding a linked mower answered. | no body |
Update Base Station Firmware
Install the offered firmware (can_manage_mowers and the plan feature control): the command base_station_firmware_update goes to a linked mower, which relays it to the vendor; follow it at status_url. The mower refuses it while it mows, returns, updates or drives, or when the version is not the offered one.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
base_station_id |
path | string (uuid) | yes |
Request body (required): application/json BaseStationFirmwareUpdateIn
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json CommandAccepted
|
| 403 | The caller lacks the relation on the account. | no body |
| 404 | No such base station in the caller's account. | no body |
| 409 |
base-station-not-linked: no mower is linked to it. |
no body |
| 422 |
mower_id is not linked to the base station. |
no body |
Set Mower Base Station
Link the mower to an RTK base station of the account, or unlink it with null (can_manage_mowers on the mower). A cloud base station serves cloud mowers of its own linked account, the simulated one simulated mowers. Publishes mower.updated: the Device-Gateway reconnects the mower with the base station.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json MowerBaseStationIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerOut
|
| 403 | The caller sees the mower but has no can_manage_mowers. |
no body |
| 404 | The mower or the base station does not exist in the account. | no body |
| 409 |
base-station-not-applicable: it cannot serve this mower. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Linked Accounts
The linked Mammotion accounts of the caller's account (no passwords).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LinkedAccountList
|
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
Create Linked Account
Link a Mammotion account: Fleet asks the Device-Gateway to log in and list the devices (gateway.cloud.discover) and stores the account with its password encrypted. Use a second Mammotion account the mowers are shared with: a login with the main account logs the phone app out.
Request body (required): application/json LinkedAccountIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json LinkedAccountDetail
|
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
| 409 | Linked. | no body |
| 422 |
linked-account-login-failed: the cloud refused the credentials. |
no body |
| 429 | Too many failed logins for this e-mail (Retry-After). |
no body |
| 503 | No credential encryption key, or no Device-Gateway or vendor cloud answered. | no body |
Get Linked Account
One linked account.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
linked_account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LinkedAccountOut
|
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Linked Account
Remove the link. Refused (409, the mowers in errors) while mowers use it. Step-up (ADR 0057): 401 reauth-required without a recent confirmation, 403 for API tokens.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
linked_account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
| 409 |
linked-account-in-use: mowers still connect through it. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Linked Devices
The devices of the last device list: name, model, IoT id, online flag, whether it is a mower and whether it is registered here or in another MowDeck account.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
linked_account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LinkedDeviceList
|
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Register Linked Mowers
Register several mowers of the linked account at once. Each one is an ordinary registration (target site and groups checked, tuples, mower.registered); devices that fail are listed in failed with the problem they would have answered. When none could be added the first problem is the answer.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
linked_account_id |
path | string (uuid) | yes |
Request body (required): application/json LinkedMowersIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json LinkedMowersOut
|
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
| 409 |
mower-already-registered (when no device could be added). |
no body |
| 422 | Unknown device, not a mower, or a device given twice. | no body |
Sync Linked Account
Read the device list again ("Konto neu einlesen"), optionally with a new password. The gateway answers from the session the account's connected mowers share when there is one (a second login would log them out). A failure is kept in last_sync_error.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
linked_account_id |
path | string (uuid) | yes |
Request body (required): application/json LinkedAccountSyncIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LinkedAccountDetail
|
| 403 | The caller lacks can_manage_mowers on the account. |
no body |
| 404 | No such linked account in the caller's account. | no body |
| 422 |
linked-account-login-failed: the cloud refused the credentials. |
no body |
| 429 | Too many failed logins for this e-mail (Retry-After). |
no body |
| 503 | No credential encryption key, or no Device-Gateway or vendor cloud answered. | no body |
Get Command
One command record of the caller's account whose mower the caller may view (404 otherwise).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
command_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json CommandView
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Connection Kinds
The connection kinds this installation accepts (MOWDECK_ALLOWED_CONNECTION_KINDS) with the option schema of each: required, optional, secret and alternative options. The web app generates its connection forms from it, so a new adapter kind needs no UI change.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ConnectionKindList
|
List Mowers
Mowers of the caller's account that the caller may view (can_view per mower).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
site_id |
query | string (uuid) or null | no | |
group_id |
query | string (uuid) or null | no |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerList
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Register Mower
Register a mower: can_manage_mowers on the target site (the account for the default site) and on each group. Publishes mower.registered after the commit. A cloud mower names a linked account and its device; 409 mower-already-registered when that physical mower is registered already (in this or another account, which is not named).
Request body (required): application/json MowerIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json MowerOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Mower
One mower (can_view, hidden otherwise).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Update Mower
Change name, model, serial, connection or site (can_manage_mowers; a new site needs it too). Publishes mower.updated when name, connection or site changed.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json MowerPatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Mower
Remove the mower and its tuples; publishes mower.removed. Step-up: 401 reauth-required without a recent passkey or password confirmation, 403 for API tokens (ADR 0057).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Area Names
The custom names of the mower's map areas (can_view, hidden otherwise). The same names come with the mower (MowerOut.area_names).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AreaNamesOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Set Area Name
Name one map area in MowDeck (can_control; 403 when the mower is visible, else 404). null or a blank name drops the custom name. The mower keeps its own names: nothing is sent to the mower. Publishes fleet.mower.area_names_changed after a change; answers all custom names of the mower.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
area_id |
path | string | yes |
MowerMap.areas[].id; min length 1; max length 128 |
Request body (required): application/json AreaNameIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AreaNamesOut
|
| 403 | The caller sees the mower but has no can_control. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 422 | The name has more than 60 characters after trimming. | no body |
Open Camera Session
A short-lived live camera session: can_view on the mower (hidden otherwise) and the plan feature camera; audited as mower.camera_opened with the transport used.
transport (ADR 0045, default auto): relay opens a lease on MowDeck's camera relay and answers its session (provider relay: WHEP URLs per camera, a ticket, lease_id; renew it every heartbeat_seconds, delete it when the page goes away). direct asks the Device-Gateway for the vendor session (ADR 0032; provider agora: the browser joins with the Agora Web SDK, fake: a test pattern). auto uses the relay and falls back to direct only when the relay cannot serve the mower's camera provider or is not deployed. The token or ticket is a secret: the response is never cached; ask again before expires_at.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body: application/json CameraSessionIn or null
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json CameraSession
|
| 403 | The plan does not include the feature camera. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
camera-unsupported: the mower's connection has no camera; camera-relay-unsupported: transport relay, but the relay has no source for the mower's camera provider; camera-budget: a camera limit refused the stream. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | The Device-Gateway, the vendor cloud or (transport relay) the camera relay did not answer, or the mower is offline. |
no body |
Close Camera Session
End a relay camera lease (ADR 0045): the page was left or hidden. Idempotent: an unknown or already closed lease, or no relay at all, is 204 as well. can_view on the mower; only the user who opened the lease ends it (another user's lease is 404 and keeps running); no plan check (ending a stream is always allowed).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
lease_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 404 | The mower is not visible, or the lease is another account's or was opened by another user. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | The camera relay did not answer in time. | no body |
Renew Camera Session
The heartbeat of a relay camera lease (ADR 0045): extends it and answers the same session with a fresh ticket (for reconnects). can_view on the mower and the plan feature camera; only the user who opened the lease renews it; never cached.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
lease_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json CameraSession
|
| 403 | The plan does not include the feature camera. |
no body |
| 404 | The mower is not visible, or the lease is unknown, expired, detached, of another account or opened by another user. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | The camera relay is not deployed or did not answer. | no body |
Camera Snapshot
A still image of the mower's camera for API clients (can_view on the mower, hidden otherwise, and the plan feature camera): taken by the Device-Gateway with the mower's own photo function or through the camera relay, keeping every camera limit (a sleeping mower is not woken). At most one new image per mower every MOWDECK_CAMERA_SNAPSHOT_MIN_INTERVAL_SECONDS (30 s); requests in between get the last one. A new image is audited as mower.camera_snapshot; Fleet never stores it.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | The image, with X-Snapshot-Taken-At (ISO 8601). |
image/jpeg any, image/png any |
| 403 | The plan does not include the feature camera. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
camera-unsupported: the mower's connection cannot take a photo. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | No Device-Gateway holds the mower or none answered in time, the mower is offline or asleep, or a camera limit (battery, budget) refused the image. | no body |
List Mower Commands
Command records of the mower (can_view, hidden otherwise).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
before |
query | string (date-time) or null | no | |
limit |
query | integer | no | min 1; max 200; default 50
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json CommandPageOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Send Command
Send a command. The relation depends on the kind: can_control (start, pause, resume, dock, blade height, speed), can_drive (manual drive, spot mow, drive calibration, drive speed setting), can_emergency_stop (emergency stop, equals can_view). Checked before any database or bus access: 403 when the mower is visible, 404 when not.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json CommandRequest
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json CommandAccepted
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Set Drive Calibration
Store the result of a drive calibration (can_drive, 403 when the mower is visible, else 404): the values a finished drive_calibrate reported in MowerState.drive_calibration.result.calibration. Fleet keeps them as managed options of the mower's ble_bridge link (the link's key stays as it is), or in the connection options of a connection kind that takes them (the simulator), and replaces a stored calibration. Audits mower.drive_calibration_set and publishes mower.updated, so the Device-Gateway hands the calibration to every spot run. Answers the stored calibration; the mower shows it as MowerOut.drive_calibration.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json DriveCalibration
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json DriveCalibration
|
| 403 | The caller sees the mower but has no can_drive. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
drive-calibration-not-applicable: the mower has no ble_bridge link and its connection options take no calibration. |
no body |
| 422 | A value out of range. | no body |
Delete Drive Calibration
Forget the stored drive calibration (can_drive, 403 when the mower is visible, else 404); spot runs then go without one. Without a stored calibration nothing changes. Audits mower.drive_calibration_removed and publishes mower.updated.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 403 | The caller sees the mower but has no can_drive. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Drive Sessions
Manual drive sessions of the mower (the joystick audit: who, when, how it ended, frame counts; can_view, hidden otherwise). Frames themselves are not stored.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
before |
query | string (date-time) or null | no | |
limit |
query | integer | no | min 1; max 200; default 50
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json DriveSessionPageOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Check Firmware
Ask the vendor for firmware updates now (can_view, hidden otherwise; ADR 0038). Fleet relays the request to the Device-Gateway that holds the mower, which asks through the mower's connection and answers the fresh FirmwareInfo (installed and available version, release notes, update state); the same information arrives with telemetry as MowerState.firmware_info. Installing is the command firmware_update (can_manage_mowers).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json FirmwareInfo
|
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
firmware-check-unsupported: the mower's connection cannot ask the vendor (no cloud link). |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | The mower is offline, the vendor did not answer, or no Device-Gateway answered in time. | no body |
Set Mower Groups
Make the mower a member of exactly these groups (can_manage_mowers on the mower and on every added or removed group).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json MowerGroupsIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Bridge Link
The mower's Bluetooth bridge link (can_view, hidden otherwise): its options with the key masked and the cached bridge information of the last scan. The live link state comes with telemetry (MowerState.links.ble_bridge).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LinkOut
|
| 404 | The mower is not visible or has no bridge link. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Set Bridge Link
Create or replace the mower's Bluetooth bridge link (can_manage_mowers, hidden otherwise): the bridge's host, port and API encryption key, the mower's Bluetooth address and name (from the scan) and the blade settings for manual driving. The options are validated with the ble_bridge schema of GET /connection-kinds; the key is stored encrypted and never returned (***; sending *** keeps it). Audits mower.link_set and publishes mower.updated with the full registration, so the Device-Gateway opens the link.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json BridgeLinkIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LinkOut
|
| 403 | The caller sees the mower but has no can_manage_mowers. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
link-not-applicable: the mower's connection kind carries no Bluetooth bridge link (decided by the connection-kind registry, GET /connection-kinds). |
no body |
| 422 | An option the ble_bridge schema refuses (#/links/ble_bridge/<key>). |
no body |
| 503 | Fleet has no credential encryption key. | no body |
Delete Bridge Link
Remove the mower's Bluetooth bridge link (can_manage_mowers, hidden otherwise). Audits mower.link_removed and publishes mower.updated without the link, so the Device-Gateway closes it.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 403 | The caller sees the mower but has no can_manage_mowers. |
no body |
| 404 | The mower is not visible or has no bridge link. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Check Bridge Link
Scan again through the stored link ("re-check", can_manage_mowers, hidden otherwise): the stored host, port and key; the reply is as for the scan and the link's proxy_info (bridge firmware, outdated flag) is refreshed. While the Device-Gateway holds the link open it answers from the live scanner.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json BridgeScanReply
|
| 403 | The caller sees the mower but has no can_manage_mowers. |
no body |
| 404 | The mower is not visible or has no bridge link. | no body |
| 409 |
link-not-applicable: the connection kind carries no bridge link; bridge-scan-unsupported: the Device-Gateway cannot scan through this bridge. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | No Device-Gateway answered in time or holds the mower right now. | no body |
Scan Bridge
Look for the mower through a Bluetooth bridge before storing the link (can_manage_mowers, hidden otherwise). Fleet relays the request to the Device-Gateway that holds the mower; the gateway connects to the bridge at host:port with the key, reads the bridge's information and collects mower advertisements for up to 30 s (early when the expected name shows up). The answer is the gateway's BridgeScanReply: proxy as soon as the bridge answered, devices seen so far, and error for the outcomes the user must act on (unreachable, auth_failed, timeout, busy) — these are a 200 with the reply, so a timeout still shows the bridge and the other mowers seen. When the mower already has a link to the same bridge its proxy_info is refreshed. *** as key means the stored key. The key is never returned or logged.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json BridgeScanIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json BridgeScanReply
|
| 403 | The caller sees the mower but has no can_manage_mowers. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
link-not-applicable: the connection kind carries no bridge link; bridge-scan-unsupported: the Device-Gateway cannot scan through this bridge. |
no body |
| 422 |
*** as key without a stored link (#/links/ble_bridge/noise_psk). |
no body |
| 503 | No Device-Gateway answered in time or holds the mower right now. | no body |
Set Mow Defaults
Keep the mowing defaults of the mower (can_control; 403 when the mower is visible, else 404): the pattern settings every client starts with (web start sheet, Home Assistant, schedules). pattern: null drops them. Nothing is sent to the mower; a start still names its own pattern in StartMow.pattern. Whether the mower runs the pattern is its capabilities' business (native_patterns). Answers the mower with mow_defaults.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json MowDefaultsIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowerOut
|
| 403 | The caller sees the mower but has no can_control. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 422 | Unknown pattern, a value out of range or an unknown key. | no body |
Preview Mow Path
Let the mower plan the route of a start (areas and pattern as for start_mow) without starting it, as the vendor app does before a start: can_control on the mower (hidden otherwise) and the plan feature control. Fleet relays the request to the Device-Gateway that holds the mower; planning and fetching the route take a few seconds to about a minute (over 4G longer), so clients show progress and allow up to 90 s. The route is not stored; the start uses the same areas and pattern and the mower plans the same route again.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json PathPreviewRequest
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MowPath
|
| 403 | The plan does not include the feature control. |
no body |
| 404 | The mower does not exist or is not visible to the caller. | no body |
| 409 |
path-preview-unsupported: the connection cannot plan without starting; path-preview-rejected: a job runs, or the areas or pattern do not fit. |
no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
| 503 | The Device-Gateway did not answer or the mower is offline. | no body |
| 504 |
gateway-timeout: the mower did not hand back its route in time. |
no body |
List Groups
Groups of the caller's account that the caller may view, optionally of one site.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
site_id |
query | string (uuid) or null | no |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json GroupList
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Create Group
A new group (can_manage_mowers on the parent site, or the account if cross-site).
Request body (required): application/json GroupIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json GroupOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Group
One group with the mowers the caller may view (can_view, hidden otherwise).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
group_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json GroupOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Update Group
Rename or move to another site (can_manage_mowers on the group and the new site).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
group_id |
path | string (uuid) | yes |
Request body (required): application/json GroupPatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json GroupOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Group
Delete an empty group (409 while it has mowers).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
group_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Bulk Group Command
The command for every mower of the group, checked per mower (see the site variant).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
group_id |
path | string (uuid) | yes |
Request body (required): application/json CommandRequest
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json BulkCommandAccepted
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Sites
Sites of the caller's account that the caller may view (can_view per site).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
include_default |
query | boolean | no | default false
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json SiteList
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Create Site
A new site (can_manage_mowers on the account, else 403).
Request body (required): application/json SiteIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json SiteOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Site
One site (can_view, hidden otherwise).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
site_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json SiteOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Update Site
Change name, timezone, address or coordinates (can_manage_mowers; the default site keeps its name).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
site_id |
path | string (uuid) | yes |
Request body (required): application/json SitePatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json SiteOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Site
Delete an empty site (409 for the default site or while mowers or groups use it).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
site_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Bulk Site Command
The command for every mower of the site, checked per mower.
Gate: can_bulk_command on the site (can_emergency_stop, i.e. view, for an emergency stop). Per mower: the relation of the command kind; invisible mowers are omitted.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
site_id |
path | string (uuid) | yes |
Request body (required): application/json CommandRequest
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json BulkCommandAccepted
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Postal address of a site (all optional).
| Field | Type | Required | Notes |
|---|---|---|---|
city |
string or null | no | |
country |
string or null | no | ISO 3166-1 alpha-2 |
postal_code |
string or null | no | |
street |
string or null | no |
PUT /mowers/{id}/area-names/{area_id}: the custom name; null or blank drops it. Surrounding blanks are trimmed; at most 60 characters remain (422 otherwise).
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string or null | yes |
The custom area names of a mower, by area id (areas without one are absent).
| Field | Type | Required | Notes |
|---|---|---|---|
names |
map of string | yes |
Install the firmware the vendor offers for the mower's RTK base station (MowerState.base_station.firmware_info.available, ADR 0047).
Sent to a mower linked to the base station: its connection asks the vendor's firmware service with the base station's id. Refused unless the base station's update_state is available and version equals available, no update of the base station is already installing, and the mower runs no job, spot run or drive session (it loses its RTK corrections while the base station restarts).
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"base_station_firmware_update" |
no | default "base_station_firmware_update"
|
version |
string | yes | The version to install, as offered.; min length 1; max length 64 |
POST /base-stations/{id}/firmware/update.
| Field | Type | Required | Notes |
|---|---|---|---|
mower_id |
string (uuid) or null | no | The linked mower that relays the request; default the first by name. |
version |
string | yes | The offered version (firmware_info.available).; min length 1; max length 64 |
POST /base-stations: a device of a linked account (source cloud) or the simulator's base station (simulated).
| Field | Type | Required | Notes |
|---|---|---|---|
device_name |
string or null | no |
cloud: the device (device_type rtk_base in the device list). |
linked_account_id |
string (uuid) or null | no |
cloud: the linked account whose device list names it. |
name |
string or null | no | Defaults to the device name (Simulated base station). |
source |
"cloud" | "simulated"
|
no | default "cloud"
|
GET /base-stations.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of BaseStationOut | yes |
An RTK base station. Its live state comes with the linked mowers' telemetry (MowerState.base_station).
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
device_name |
string or null | yes | |
id |
string (uuid) | yes | |
iot_id |
string or null | yes | The vendor's device id (unique across accounts). |
linked_account_id |
string (uuid) or null | yes | |
model |
string or null | yes | |
mower_ids |
array of string (uuid) | yes | The mowers linked to it, by name. |
name |
string | yes | |
source |
"cloud" | "simulated"
|
yes | |
updated_at |
string (date-time) | yes |
PATCH /base-stations/{id}.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | yes | min length 1; max length 100 |
PUT /mowers/{id}/links/ble_bridge: a Bluetooth bridge (an ESPHome Bluetooth proxy) next to the mower's connection. noise_psk is write-only; *** keeps the stored key.
| Field | Type | Required | Notes |
|---|---|---|---|
allow_manual_blades |
boolean | no | Blades may run while the mower is driven manually.; default false
|
ble_address |
string | yes | The mower's Bluetooth address (from the scan).; min length 1; max length 32 |
device_name |
string or null | no | The mower's Bluetooth name (from the scan); the cloud device name when omitted. |
host |
string | yes | Host name or IP of the bridge.; min length 1; max length 253 |
manual_blade_height_mm |
integer or null | no | Blade height for manual driving. |
manual_drive_speed_mps |
number or null | no |
max_run_speed the mower gets when a drive session opens (ADR 0042); omitted: the mower's own speed setting for manual driving, at most 1.0 m/s. |
noise_psk |
string | yes | The bridge's API encryption key (api.encryption.key of an ESPHome bridge); *** keeps the stored key.; min length 1; max length 256 |
port |
integer | no | The bridge's API port.; min 1.0; max 65535.0; default 6053
|
The error of a :class:BridgeScanReply; detail never echoes the key.
| Field | Type | Required | Notes |
|---|---|---|---|
code |
BridgeScanErrorCode | yes | |
detail |
string | yes | max length 500 |
held_by |
string or null | no | For already_connected: the name of the mower entry whose connection holds the mower through this bridge. |
Why a bridge scan gave no result.
Type: "unreachable" | "auth_failed" | "timeout" | "busy" | "unsupported" | "not_found" | "forbidden" | "already_connected"
POST /mowers/{id}/links/ble_bridge/scan: where the bridge is and its key (***: the stored key of the existing link).
| Field | Type | Required | Notes |
|---|---|---|---|
host |
string | yes | min length 1; max length 253 |
noise_psk |
string | no | The bridge's API encryption key; *** means the stored key.; min length 1; max length 256; default "***"
|
port |
integer | no | min 1.0; max 65535.0; default 6053
|
Reply to :class:BridgeScanRequest.
proxy is set as soon as the proxy answered, also with a timeout error (the bridge works, the mower was not seen); devices lists every mower advertisement seen, so the client can offer a different mower than expected. error is null when the scan succeeded.
| Field | Type | Required | Notes |
|---|---|---|---|
devices |
array of ScannedDevice | no | max items 50 |
error |
BridgeScanError or null | no | |
proxy |
ProxyInfo or null | no |
Answer (202) to a command for every mower of a site or group.
| Field | Type | Required | Notes |
|---|---|---|---|
bulk_id |
string (uuid) | yes | |
items |
array of BulkCommandItem | no | |
kind |
string | yes | min length 1; max length 64 |
target_id |
string (uuid) | yes | |
target_type |
"site" | "group"
|
yes |
One mower of a bulk command. Mowers the caller cannot see are omitted.
| Field | Type | Required | Notes |
|---|---|---|---|
command_id |
string (uuid) or null | no | |
expires_at |
string (date-time) or null | no | |
mower_id |
string (uuid) | yes | |
outcome |
BulkCommandOutcome | yes |
What happened to one mower of a bulk command.
Type: "accepted" | "forbidden" | "not_published"
Channel encryption the client must configure before joining (Agora setEncryptionConfig).
| Field | Type | Required | Notes |
|---|---|---|---|
key |
string | yes | The secret, used verbatim.; min length 1; max length 256 |
mode |
string | yes | Agora encryption mode, for Mammotion aes-256-gcm2.; max length 32 |
salt |
string or null | no | Base64 salt (32 bytes decoded) for the gcm2 modes; null when not sent. |
One camera of the mower.
| Field | Type | Required | Notes |
|---|---|---|---|
id |
string | yes | Camera id as the vendor names it.; min length 1; max length 64 |
name |
string | yes | A short display name, e.g. Front left.; max length 100 |
placement |
CameraPlacement or null | no | Where the camera sits, if known. A front_left and a front_right camera form a stereo pair the client may show side by side. |
uid |
integer or null | no | Agora uid the mower publishes this camera under, if known. Clients fall back to the first remote user that publishes video. |
Where a camera sits on the mower. Clients pair front_left and front_right for the side-by-side view and stereo frames (both front cameras of a LUBA 2 AWD X).
Type: "front_left" | "front_right" | "front" | "rear"
Who delivers the video.
Type: "agora" | "fake" | "relay"
The vendor's video budget (Mammotion meters video over 4G only).
| Field | Type | Required | Notes |
|---|---|---|---|
total_minutes |
number | yes | min 0.0 |
used_minutes |
number | yes | min 0.0 |
Credentials for one viewer to join the live video of one mower.
Provider relay needs the relay endpoint and carries no vendor secrets (token and app_id empty, no encryption); expires_at is then the ticket's expiry. Every other provider has no relay endpoint.
| Field | Type | Required | Notes |
|---|---|---|---|
app_id |
string | yes | Agora app id (empty for fake).; max length 128 |
cameras |
array of CameraInfo | no | max items 8 |
channel |
string | yes | Agora channel name (64 bytes at most).; max length 64 |
encryption |
CameraEncryption or null | no | Set when the channel is encrypted. |
expires_at |
string (date-time) | yes | When the token stops working; clients request a new session before. |
provider |
CameraProvider | yes | |
quota |
CameraQuota or null | no | The video budget, when the vendor reports one. |
relay |
RelayEndpoint or null | no | Set exactly when provider is relay (ADR 0045). |
token |
string | yes | Short-lived Agora token. Never log it.; max length 2048 |
uid |
integer | yes | The viewer's Agora uid (bound to the token).; min 0.0; max 4294967295.0 |
POST /mowers/{id}/camera/session (optional body): how the client wants the video.
| Field | Type | Required | Notes |
|---|---|---|---|
transport |
CameraTransport | no |
auto (default): the camera relay, the direct vendor path only when the relay cannot serve the mower's camera provider or is not deployed; relay: only the relay, its errors are answered; direct: the vendor session (ADR 0032).; default "auto"
|
How a client wants to reach the camera (ADR 0045). Chosen per browser; Fleet decides.
Type: "auto" | "relay" | "direct"
Answer (202) to a command for one mower: Fleet published it; results follow.
| Field | Type | Required | Notes |
|---|---|---|---|
command_id |
string (uuid) | yes | |
correlation_id |
string | yes | pattern ^[A-Za-z0-9._:\-]{1,128}$
|
expires_at |
string (date-time) | yes | |
issued_at |
string (date-time) | yes | |
kind |
string | yes | min length 1; max length 64 |
mower_id |
string (uuid) | yes | |
priority |
CommandPriority | yes | |
status |
"accepted" |
no | default "accepted"
|
status_url |
string | yes | Where to read the command record, e.g. /api/v1/fleet/commands/<id>. |
GET /mowers/{id}/commands: newest first; pass next_before as before.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of CommandView | yes | |
next_before |
string (date-time) or null | yes |
Delivery priority of a command. Only :class:EmergencyStop uses emergency.
Type: "normal" | "emergency"
Body of POST .../commands for a mower, a group or a site.
ttl_seconds shortens or extends the expiry within the service's limit; Fleet ignores it for manual_drive and emergency_stop, which always use their own short expiry.
| Field | Type | Required | Notes |
|---|---|---|---|
command |
StartMow or PauseMow or ResumeMow or ReturnToDock or EmergencyStop or SetBladeHeight or SetSpeed or SetLight or FirmwareUpdate or BaseStationFirmwareUpdate or SpotMow or SpotStop or DriveCalibrate or SetDriveSpeed or SetSetting or RestartMower or SyncMap or RelocateDock or LeaveDock or ResyncRtk or ManualDrive | yes | |
ttl_seconds |
integer or null | no |
Status of a command record in Fleet.
Type: "pending" | "accepted" | "rejected" | "executed" | "expired" | "failed"
A command record as clients read it (GET /commands/{id}).
| Field | Type | Required | Notes |
|---|---|---|---|
bulk_id |
string (uuid) or null | no | |
command_id |
string (uuid) | yes | |
correlation_id |
string | yes | pattern ^[A-Za-z0-9._:\-]{1,128}$
|
end_job |
boolean or null | no | For a return_to_dock: whether it also ended the job; None for other kinds. |
expires_at |
string (date-time) | yes | |
issued_at |
string (date-time) | yes | |
issued_by |
PrincipalRef | yes | |
kind |
string | yes | min length 1; max length 64 |
mower_id |
string (uuid) | yes | |
origin |
string or null | no | Service that issued the command on behalf of issued_by (e.g. scheduler); None for commands sent through the API. |
pattern |
object or null | no | For a start_mow on map areas: the pattern settings it was sent with (StartMow.pattern, mostly MowPattern keys); None otherwise or when it had none. |
plan_hash |
string or null | no | Hash of the spot plan of a start_mow with spot_plan, if any. |
priority |
CommandPriority | yes | |
reason |
string or null | no | |
result_at |
string (date-time) or null | no | Time of the latest result applied to the record. |
schedule_id |
string (uuid) or null | no | The schedule that issued the command, if any. |
status |
CommandState | yes |
A set of alternative options (e.g. password or credential reference).
| Field | Type | Required | Notes |
|---|---|---|---|
key |
string | yes | |
title |
string | yes |
How the Device-Gateway is connected to the mower.
Type: "ble_bridge" | "wifi" | "cloud" | "simulated"
GET /connection-kinds: the kinds accepted here, in the order the app offers them.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of ConnectionKindOut | yes |
A connection kind this installation accepts, with its option schema.
| Field | Type | Required | Notes |
|---|---|---|---|
description |
string | yes | |
extra_options |
boolean | yes | Keys outside options are accepted and kept (adapter specific). |
groups |
array of ConnectionGroupOut | yes | |
kind |
string | yes | |
linked_account |
boolean | no | Mowers of this kind come from a linked vendor account (/linked-accounts): register them with linked_account_id and device_name.; default false
|
options |
array of ConnectionOptionOut | yes | |
title |
string | yes |
One option of a connection kind (the web app builds its form from these).
| Field | Type | Required | Notes |
|---|---|---|---|
advanced |
boolean | yes | |
default |
string or integer or number or boolean or null | yes | |
description |
string | yes | |
examples |
array of string | yes | |
format_hint |
string or null | yes | |
group |
string or null | yes | Options with the same group are alternatives: one of them is required. |
key |
string | yes | |
managed |
boolean | no | Set by Fleet (from the linked account's device list, or a stored drive calibration): shown, not editable.; default false
|
maximum |
number or null | yes | |
minimum |
number or null | yes | |
pattern |
string or null | yes | Regular expression a string value must match. |
required |
boolean | yes | |
secret |
boolean | yes | Write-only: answered as ***; sending *** back keeps the stored value. |
title |
string | yes | English label; the app translates the options it knows. |
type |
"string" | "integer" | "number" | "boolean"
|
yes |
What a discovered device is (ADR 0047).
Type: "mower" | "rtk_base" | "other"
Measure what the stick values mean on the ground (ADR 0042).
MowDeck drives a few short steps with the blades off (forward at linear 0.3, 0.5, 0.7 and 1.0, then turns in place at angular ±0.3, ±0.6 and ±1.0, each step_s long, zero frames in between). Each step is measured over its steady window only (without the first 1.5 s, while the mower reacts), and MowDeck fits the full-scale ground speed, the full-scale yaw rate and the dead zone. Needs MowerCapabilities.manual_drive, an idle mower out of its dock with a fixed RTK position and about 2 m of free lawn straight ahead. Progress and the result arrive in MowerState.drive_calibration; SpotStop and EmergencyStop end it.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"drive_calibrate" |
no | default "drive_calibrate"
|
step_s |
number | no | Duration of each step in seconds.; min 5.0; max 12.0; default 6.0
|
The fitted drive behaviour of one mower, as stored in the drive link's options.
| Field | Type | Required | Notes |
|---|---|---|---|
calibrated_at |
string (date-time) | yes | |
dead_zone |
number | no |
linear below which the mower stands.; min 0.0; max 0.9; default 0.0
|
drive_speed_setting |
number or null | no | The vendor's manual-driving speed setting during the calibration (MowerState.drive_speed_mps); null when the connection has none. |
full_speed_mps |
number | yes | Ground speed at linear = 1.; max 5.0; greater than 0.0 |
full_yaw_rate_dps |
number | yes | Yaw rate at angular = ±1 in degrees per second.; max 720.0; greater than 0.0 |
turn_dead_zone |
number | no |
angular below which the mower does not turn.; min 0.0; max 0.9; default 0.0
|
Why a drive session ended.
Type: "client_stop" | "socket_closed" | "revoked" | "token_expired" | "max_duration" | "mower_refused" | "mower_busy" | "replaced" | "expired" | "completed" | "aborted"
GET /mowers/{id}/drive-sessions: newest first; pass next_before as before.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of DriveSessionView | yes | |
next_before |
string (date-time) or null | yes |
A drive session as the audit API shows it (GET /mowers/{id}/drive-sessions).
| Field | Type | Required | Notes |
|---|---|---|---|
blade_on_allowed |
boolean | yes | |
end_reason |
DriveEndReason or null | no | |
ended_at |
string (date-time) or null | no | |
expires_at |
string (date-time) | yes | |
frames |
integer or null | no | |
frames_dropped |
integer or null | no | |
mower_id |
string (uuid) | yes | |
origin |
string or null | no | Service that drove on behalf of started_by (e.g. vision); None for the joystick. |
session_id |
string (uuid) | yes | |
started_at |
string (date-time) | yes | |
started_by |
PrincipalRef | yes |
Stop blades and wheels immediately. Always sent with priority = emergency.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"emergency_stop" |
no | default "emergency_stop"
|
The firmware state of a mower (MowerState.firmware_info).
| Field | Type | Required | Notes |
|---|---|---|---|
available |
string or null | no | The newest version the vendor offers for this mower; null when none or unknown. |
checked_at |
string (date-time) or null | no | When the vendor was last asked; null when never. |
failure_reason |
string or null | no | Why the last update failed, if known. |
installed |
string or null | no | The version running on the mower. |
progress |
integer or null | no | Percent done while installing, if reported. |
release_notes |
string or null | no | Release notes of available, if given. |
update_state |
"idle" | "available" | "installing" | "failed" | "unknown"
|
no | default "unknown"
|
Install the firmware version the vendor offers (MowerState.firmware_info.available).
The adapter refuses it unless update_state is available and version equals available (a stale client), the mower is docked with enough battery (it need not be charging: a full mower stops charging), no job or drive session runs and no update is already installing. While it runs the mower reports the activity updating.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"firmware_update" |
no | default "firmware_update"
|
version |
string | yes | The version to install, as offered.; min length 1; max length 64 |
POST /groups: site_id null or missing makes a cross-site group.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | yes | min length 1; max length 100 |
site_id |
string (uuid) or null | no |
GET /groups.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of GroupOut | yes |
A group; mower_ids lists only the mowers the caller may view.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
created_by |
string (uuid) | yes | |
id |
string (uuid) | yes | |
mower_ids |
array of string (uuid) or null | no | |
name |
string | yes | |
site_id |
string (uuid) or null | yes | |
updated_at |
string (date-time) | yes |
PATCH /groups/{id}: site_id: null makes it a cross-site group.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string or null | no | |
site_id |
string (uuid) or null | no |
| Field | Type | Required | Notes |
|---|---|---|---|
detail |
array of ValidationError | no |
Drive out of the charging station and stop a short way in front of it (needs MowerCapabilities.undock). A motion command: only from the dock, never during a sensor stop; it ends an open drive session like a job command.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"leave_dock" |
no | default "leave_dock"
|
A linked account with its devices (answer of create and sync).
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
device_count |
integer | yes | |
devices |
array of LinkedDeviceOut | yes | |
email |
string | yes | |
id |
string (uuid) | yes | |
last_sync_error |
string or null | yes | Why the last re-read failed, if it did. |
last_synced_at |
string (date-time) or null | yes | When the device list was last read successfully. |
mower_count |
integer | yes | Mowers of this account that connect through it. |
provider |
string | yes | |
updated_at |
string (date-time) | yes |
POST /linked-accounts: the Mammotion account to link (the only provider so far). The password is write-only.
| Field | Type | Required | Notes |
|---|---|---|---|
email |
string | yes | min length 3; max length 254 |
password |
string | yes | min length 1; max length 256 |
GET /linked-accounts.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of LinkedAccountOut | yes |
A linked account; the password is never returned.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
device_count |
integer | yes | |
email |
string | yes | |
id |
string (uuid) | yes | |
last_sync_error |
string or null | yes | Why the last re-read failed, if it did. |
last_synced_at |
string (date-time) or null | yes | When the device list was last read successfully. |
mower_count |
integer | yes | Mowers of this account that connect through it. |
provider |
string | yes | |
updated_at |
string (date-time) | yes |
POST /linked-accounts/{id}/sync: optionally a new password (write-only).
| Field | Type | Required | Notes |
|---|---|---|---|
password |
string or null | no |
GET /linked-accounts/{id}/devices.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of LinkedDeviceOut | yes | |
last_synced_at |
string (date-time) or null | yes |
A device of a linked account as its last device list showed it.
| Field | Type | Required | Notes |
|---|---|---|---|
base_station_id |
string (uuid) or null | no | That base station, when registered as a base station. |
device_name |
string | yes | |
device_type |
DeviceType | no |
mower, rtk_base (register it with POST /base-stations, ADR 0047) or other (not registrable).; default "other"
|
iot_id |
string or null | yes | |
is_mower |
boolean | yes | False for RTK base stations and other non-mowers. |
model |
string or null | yes | |
mower_id |
string (uuid) or null | yes | That mower, when registered as a mower. |
online |
boolean or null | yes | |
product_key |
string or null | yes | |
registered |
boolean | yes | Registered in this account: as a mower, or as a base station. |
registered_elsewhere |
boolean | yes | Registered in another MowDeck account (which one is not revealed); it cannot be added here. |
A device that could not be registered, with the problem it would have answered.
| Field | Type | Required | Notes |
|---|---|---|---|
detail |
string | yes | |
device_name |
string | yes | |
status |
integer | yes | |
type |
string | yes |
One mower of POST /linked-accounts/{id}/mowers.
| Field | Type | Required | Notes |
|---|---|---|---|
device_name |
string | yes | min length 1; max length 100 |
group_ids |
array of string (uuid) | no | max items 50 |
name |
string or null | no | |
serial |
string or null | no | |
site_id |
string (uuid) or null | no |
POST /linked-accounts/{id}/mowers: several devices of the account at once.
| Field | Type | Required | Notes |
|---|---|---|---|
mowers |
array of LinkedMowerIn | yes | min items 1; max items 50 |
Answer of the bulk registration: created mowers and failures per device.
| Field | Type | Required | Notes |
|---|---|---|---|
created |
array of MowerOut | yes | |
failed |
array of LinkedMowerFailure | yes |
An additional link of a mower (MowerOut.links[kind], the link routes).
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
kind |
string | yes | |
options |
object | yes | The link's options (host, port, ble_address, device_name, allow_manual_blades, manual_blade_height_mm, manual_drive_speed_mps and the managed drive calibration keys); secret keys show *** and sending *** back keeps the stored value. |
proxy_info |
ProxyInfo or null | no | What the last scan or check learnt about the bridge; null until one answered. The live link state is MowerState.links[kind] from telemetry. |
updated_at |
string (date-time) | yes |
One joystick sample. The mower stops when no new sample arrives within ttl_ms.
This is the dead-man switch: clients resend samples continuously while the stick is held.
| Field | Type | Required | Notes |
|---|---|---|---|
angular |
number | yes | Turn left (+) / right (-), normalised.; min -1.0; max 1.0 |
blade_on |
boolean | no | default false
|
kind |
"manual_drive" |
no | default "manual_drive"
|
linear |
number | yes | Forward (+) / backward (-), normalised.; min -1.0; max 1.0 |
ttl_ms |
integer | no | Dead-man timeout in milliseconds.; min 100.0; max 2000.0; default 1000
|
The saved mowing defaults of a mower (MowerOut.mow_defaults).
| Field | Type | Required | Notes |
|---|---|---|---|
pattern |
MowPattern | yes |
PUT /mowers/{id}/mow-defaults: the mowing defaults every client starts with. pattern: null drops them (clients then use stripes, 0 degrees, one border lap).
| Field | Type | Required | Notes |
|---|---|---|---|
pattern |
MowPatternIn or null | yes |
PUT /mowers/{id}/base-station: link the mower to a base station, or unlink it.
| Field | Type | Required | Notes |
|---|---|---|---|
base_station_id |
string (uuid) or null | yes | null removes the link. |
PUT /mowers/{id}/groups: the complete set of groups.
| Field | Type | Required | Notes |
|---|---|---|---|
group_ids |
array of string (uuid) | yes | max items 50 |
POST /mowers: without site_id the mower goes to the account's default site.
A cloud mower comes from a linked Mammotion account: linked_account_id and the device_name of its device list (connection_options then hold only adapter extras such as refresh_seconds); name defaults to the device name and model to the listed model.
| Field | Type | Required | Notes |
|---|---|---|---|
connection_kind |
ConnectionKind | yes | |
connection_options |
object | no | Adapter specific (simulator: time_scale, battery_percent; cloud: account, device_name or iot_id, credential_ref or password; ble_bridge: host, port, noise_psk, ble_address). Secret values (password, noise_psk) are never returned: responses show ***, and sending *** back keeps the stored value. |
device_name |
string or null | no | |
group_ids |
array of string (uuid) | no | max items 50 |
linked_account_id |
string (uuid) or null | no | |
model |
string or null | no | |
name |
string or null | no | |
serial |
string or null | no | |
site_id |
string (uuid) or null | no |
GET /mowers.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of MowerOut | yes |
A mower.
| Field | Type | Required | Notes |
|---|---|---|---|
area_names |
map of string | no | Custom names of map areas by area id (MowerMap.areas[].id); areas without one show the mower's own name, else Area N in map order. |
base_station_id |
string (uuid) or null | no | The RTK base station the mower is linked to (PUT /mowers/{id}/base-station, ADR 0047); its state is in the mower's telemetry (MowerState.base_station). |
connection_kind |
string | yes | |
connection_options |
object | yes | |
created_at |
string (date-time) | yes | |
created_by |
string (uuid) | yes | |
drive_calibration |
DriveCalibration or null | no | The stored drive calibration (PUT /mowers/{id}/drive-calibration): from the ble_bridge link, else from the connection options; null until one is stored. |
group_ids |
array of string (uuid) | yes | |
id |
string (uuid) | yes | |
iot_id |
string or null | no | The vendor's device id (unique across MowDeck accounts). |
linked_account_id |
string (uuid) or null | no | The linked account a cloud mower connects through. |
links |
map of LinkOut | no | Additional links next to the connection by kind (ble_bridge: a Bluetooth bridge, PUT /mowers/{id}/links/ble_bridge); empty for a mower with only its connection. |
model |
string or null | yes | |
mow_defaults |
MowDefaults or null | no | The mowing defaults every client starts with (PUT /mowers/{id}/mow-defaults); null until saved: then stripes at 0 degrees with one border lap. |
name |
string | yes | |
serial |
string or null | yes | |
site_id |
string (uuid) | yes | |
updated_at |
string (date-time) | yes |
PATCH /mowers/{id}: only the given fields change.
| Field | Type | Required | Notes |
|---|---|---|---|
connection_kind |
ConnectionKind or null | no | |
connection_options |
object or null | no | |
model |
string or null | no | |
name |
string or null | no | |
serial |
string or null | no | |
site_id |
string (uuid) or null | no |
The route a mower planned, in the local metres of its map.
| Field | Type | Required | Notes |
|---|---|---|---|
area_ids |
array of string | no | The map areas the route covers, in order. |
kinds |
array of "mow" | "edge" | "transfer" | "other" or null |
no | The kind of every polyline (same length), when known. |
path_hash |
string | yes | The vendor's id of the planned route.; min length 1; max length 32 |
planned_at |
string (date-time) | yes | When MowDeck received the route (UTC). |
points_total |
integer | yes | Number of points over all polylines.; min 0.0 |
polylines |
array of array of array of any | no | The route as polylines in driving order. |
progress |
MowPathProgress or null | no | Progress of the running job; None for a preview. |
Where the mower is along its path.
| Field | Type | Required | Notes |
|---|---|---|---|
direction |
integer | no | The vendor's traversal direction flag (0 or 1).; min 0.0; max 255.0; default 0
|
index |
integer | yes | Points done so far, counted over all polylines in order: the points with a flat index below this value are mowed.; min 0.0 |
The pattern settings of a native start (StartMow.pattern) that every client offers: the pattern, its base angle, the border laps and the path spacing, plus the job options a mower may declare in MowerCapabilities.start_options (obstacle detection, laps around no-go zones, path order, start progress; ADR 0030 amendment of 2026-10-24). An option left None is not sent, so the mower keeps its own default.
Adapters may accept further keys in StartMow.pattern; this is the common, validated part, also kept per mower as the mowing defaults in Fleet (MowerOut.mow_defaults). Whether the mower runs the pattern is decided with MowerCapabilities.native_patterns.
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number | no | Base angle of the stripes in degrees (diagonal adds 45, checkerboard crosses at 90; ignored for edge_only and random_angle).; min 0.0; max 180.0; default 0.0
|
border_laps |
integer | no | Laps along the area edge before the fill (edge_only: at least one).; min 0.0; max 4.0; default 1
|
name |
"stripes" | "diagonal" | "checkerboard" | "edge_only" | "random_angle"
|
no | The native pattern.; default "stripes"
|
obstacle_detection |
ObstacleDetection or null | no | Obstacle detection mode of the job; None keeps the mower's default. Offered modes: MowerCapabilities.start_options.obstacle_detection. |
obstacle_laps |
integer or null | no | Laps around each no-go zone; None keeps the mower's default. Model limits: MowerCapabilities.start_options.obstacle_laps_range. |
order |
PathOrder or null | no | Border laps before or after the fill; None keeps the mower's default. Offered orders: MowerCapabilities.start_options.orders. |
spacing_m |
number or null | no | Distance between neighbouring paths in metres; None for the mower's own default. Model limits: MowerCapabilities.path_spacing_range_mm. |
start_progress_pct |
integer or null | no | Start the job at this progress in percent, skipping the first part of the route; None (or 0) starts at the beginning. Model limits: MowerCapabilities.start_options.start_progress_range_pct. |
MowPattern as a request body: unknown keys are refused (422).
| Field | Type | Required | Notes |
|---|---|---|---|
angle_deg |
number | no | Base angle of the stripes in degrees (diagonal adds 45, checkerboard crosses at 90; ignored for edge_only and random_angle).; min 0.0; max 180.0; default 0.0
|
border_laps |
integer | no | Laps along the area edge before the fill (edge_only: at least one).; min 0.0; max 4.0; default 1
|
name |
"stripes" | "diagonal" | "checkerboard" | "edge_only" | "random_angle"
|
no | The native pattern.; default "stripes"
|
obstacle_detection |
ObstacleDetection or null | no | Obstacle detection mode of the job; None keeps the mower's default. Offered modes: MowerCapabilities.start_options.obstacle_detection. |
obstacle_laps |
integer or null | no | Laps around each no-go zone; None keeps the mower's default. Model limits: MowerCapabilities.start_options.obstacle_laps_range. |
order |
PathOrder or null | no | Border laps before or after the fill; None keeps the mower's default. Offered orders: MowerCapabilities.start_options.orders. |
spacing_m |
number or null | no | Distance between neighbouring paths in metres; None for the mower's own default. Model limits: MowerCapabilities.path_spacing_range_mm. |
start_progress_pct |
integer or null | no | Start the job at this progress in percent, skipping the first part of the route; None (or 0) starts at the beginning. Model limits: MowerCapabilities.start_options.start_progress_range_pct. |
How eagerly the mower avoids obstacles during a native job (MowPattern).
Which modes a mower offers depends on its model and firmware (MowerCapabilities.start_options.obstacle_detection). The names follow the vendor apps: off is the plain bump-and-turn behaviour, standard avoids obstacles it sees ahead, sensitive additionally avoids areas that are not lawn; slow_touch and less_touch exist only on older firmware.
Type: "off" | "slow_touch" | "less_touch" | "standard" | "sensitive"
Whether the border laps run before or after the fill of a native job.
Type: "border_first" | "grid_first"
Body of POST /api/v1/fleet/mowers/{id}/path-preview: the areas and pattern of a start whose route the mower should plan without starting.
| Field | Type | Required | Notes |
|---|---|---|---|
area_ids |
array of string | yes | Map area ids, in order.; min items 1; max items 64 |
pattern |
object or null | no | Pattern settings as for StartMow.pattern. |
Pause the current job.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"pause_mow" |
no | default "pause_mow"
|
What kind of subject a principal is.
Type: "user" | "subuser" | "api_token" | "service"
A compact reference to a principal, embedded in commands and audit records.
| Field | Type | Required | Notes |
|---|---|---|---|
display_name |
string or null | no | |
kind |
PrincipalKind | yes | Kind of subject. |
subject |
string (uuid) | yes | Stable subject id (JWT sub). |
token_id |
string (uuid) or null | no | Token id (JWT jti), if known. |
What a scan learnt about the bridge itself (ESPHome device_info).
| Field | Type | Required | Notes |
|---|---|---|---|
bluetooth_mac |
string or null | no | The bridge's own Bluetooth address. |
checked_at |
string (date-time) | yes | When the gateway read this information. |
compiled_at |
string or null | no | |
esphome_version |
string or null | no | |
outdated |
boolean | no | default false
|
outdated_reason |
string or null | no | |
project_name |
string or null | no |
esphome.project.name, if set. |
project_version |
string or null | no |
esphome.project.version, if set. |
proxy_name |
string | yes | The ESPHome node name.; max length 100 |
Where and with what a client plays a relay session (provider relay).
| Field | Type | Required | Notes |
|---|---|---|---|
heartbeat_seconds |
integer | no | How often the client renews the lease while the page is visible.; min 5.0; max 60.0; default 15
|
lease_id |
string (uuid) | yes | The viewer's lease; renew and detach name it. |
ticket |
string | yes | Short-lived ticket signed by the relay, bound to account, mower, lease and paths. Sent as the WHEP bearer token. Never log it.; min length 1; max length 2048 |
tiles |
array of RelayTile | yes | min items 1; max items 8 |
One camera as the relay serves it: a WHEP endpoint per camera.
| Field | Type | Required | Notes |
|---|---|---|---|
available |
boolean or null | no | Whether this camera delivers video: true once its stream appeared, false when it has not appeared a while after the session went live (a camera the vendor lists but the mower never publishes), null while not known yet. Clients offer only cameras that are not false. |
camera_id |
string | yes | The CameraInfo.id this endpoint shows.; min length 1; max length 64 |
whep_url |
string | yes | WHEP endpoint of this camera: an absolute path on the MowDeck origin or an http(s) URL. The path carries a random session token, never the mower id.; min length 2; max length 512; pattern `^(/ |
Delete the stored position of the charging station, so the mower learns it again (after the station was moved). Only while the mower stands in its dock (docked or charging): out on the lawn it would lose its way home.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"relocate_dock" |
no | default "relocate_dock"
|
Restart the mower. Only at rest (docked, charging or idle), without an open drive session or a command waiting for its confirmation; the mower is offline while it boots.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"restart_mower" |
no | default "restart_mower"
|
Resume a paused job.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"resume_mow" |
no | default "resume_mow"
|
Read the RTK origin and the dock pose again; the map is rebuilt with what the mower answers. No motion; allowed in every activity except during a firmware update.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"resync_rtk" |
no | default "resync_rtk"
|
Pause or end the job and drive back to the charging station.
| Field | Type | Required | Notes |
|---|---|---|---|
end_job |
boolean | no | default false
|
kind |
"return_to_dock" |
no | default "return_to_dock"
|
One mower advertisement the bridge saw during a scan.
| Field | Type | Required | Notes |
|---|---|---|---|
address |
string | yes | Bluetooth address.; min length 1; max length 32 |
name |
string | yes | The Bluetooth name the mower advertises.; min length 1; max length 100 |
rssi |
integer | yes | Signal strength at the bridge in dBm.; min -128.0; max 20.0 |
Set the cutting height.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"set_blade_height" |
no | default "set_blade_height"
|
mm |
integer | yes | Blade height in millimetres.; min 10.0; max 120.0 |
Change the vendor's speed setting for manual driving (MowerCapabilities.drive_speed_setting; the mower scales the stick by it).
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"set_drive_speed" |
no | default "set_drive_speed"
|
speed_mps |
number | yes | max 5.0; greater than 0.0 |
Switch the mower's light (the camera's headlamp on Mammotion mowers) on or off.
Needs MowerCapabilities.light. Allowed in every activity, also during an error: the light is harmless and AI assist switches it on to photograph a stuck mower at night.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"set_light" |
no | default "set_light"
|
on |
boolean | yes | True switches the light on, False off. |
Change one of the mower's own settings (ADR 0046).
The key must be declared in MowerCapabilities.settings and the value must fit its declaration (type, range, step, options); the controller rejects anything else before it reaches the mower. A setting never makes the mower move. The new value arrives in MowerState.settings once the mower reports it.
| Field | Type | Required | Notes |
|---|---|---|---|
key |
string | yes | pattern ^[a-z][a-z0-9_]{0,47}$
|
kind |
"set_setting" |
no | default "set_setting"
|
value |
boolean or integer or string or TimeWindow or null | yes | The new value: true or false, a whole number, an option, a time window {start, end}, or null to switch a time window off. |
Set the driving speed while mowing.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"set_speed" |
no | default "set_speed"
|
mps |
number | yes | Speed in metres per second.; max 2.0; greater than 0.0 |
POST /sites. latitude and longitude (both or none) locate the site for the Scheduler's rain pause.
| Field | Type | Required | Notes |
|---|---|---|---|
address |
Address or null | no | |
latitude |
number or null | no | WGS84 latitude in degrees |
longitude |
number or null | no | WGS84 longitude in degrees |
name |
string | yes | min length 1; max length 100 |
timezone |
string or null | no | IANA name |
GET /sites.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of SiteOut | yes |
A site.
| Field | Type | Required | Notes |
|---|---|---|---|
address |
object or null | yes | |
created_at |
string (date-time) | yes | |
created_by |
string (uuid) or null | yes | |
id |
string (uuid) | yes | |
is_default |
boolean | yes | |
latitude |
number or null | no | |
longitude |
number or null | no | |
name |
string | yes | |
timezone |
string | yes | |
updated_at |
string (date-time) | yes |
PATCH /sites/{id}: only the given fields change (address: null clears it).
| Field | Type | Required | Notes |
|---|---|---|---|
address |
Address or null | no | |
latitude |
number or null | no | WGS84 latitude in degrees |
longitude |
number or null | no | WGS84 longitude in degrees |
name |
string or null | no | |
timezone |
string or null | no |
A round spot: radius_m around center_wgs84 ([lat, lon]).
| Field | Type | Required | Notes |
|---|---|---|---|
center_wgs84 |
array of any | yes | min items 2; max items 2 |
radius_m |
number | yes | max 10.0; greater than 0.0 |
Mow a small spot by driving the mower along plan with joystick frames (ADR 0039).
Unlike StartMow.spot_plan the mower runs no job of its own: MowDeck's gateway steers it over the drive link (needs MowerCapabilities.manual_drive, a fixed RTK position and an idle mower, or a docked one when the connection can leave the dock by itself: MowerCapabilities.undock, ADR 0041). A transit with the blades off takes the mower from where it stands to the start of the plan; with return_to_dock it is sent home after the run (also after an abort that left it healthy, never after a stop). The blades stay off (a dry run) unless blades and confirm_blades are both true and the mower allows blades while driving (manual_drive_blades). spot records what the user chose; the route is plan. Progress arrives in MowerState.spot_run; SpotStop ends the run.
| Field | Type | Required | Notes |
|---|---|---|---|
blades |
boolean | no | Cut while driving (else a dry run).; default false
|
confirm_blades |
boolean | no | The user confirmed the blades separately; required with blades.; default false
|
kind |
"spot_mow" |
no | default "spot_mow"
|
plan |
SpotMowPlan | yes | |
return_to_dock |
boolean | no | Send the mower back to its charging station after the run (also after an abort that left it healthy; never after a stop).; default true
|
speed_mps |
number | no | Driving speed of the run in metres per second (at most 0.3).; max 0.3; greater than 0.0; default 0.2
|
spot |
SpotCircle or SpotPolygon or null | no | The spot as the user chose it (audit only). |
turn_style |
TurnStyle or null | no | How the run turns at lane ends (ADR 0043); null: the mower's own setting (MowerState.turn_style), else arc. multi_point falls back to arc on a drive link without drive_reverse. The plan should be computed with the same style. |
A computed mowing route for StartMow.spot_plan.
| Field | Type | Required | Notes |
|---|---|---|---|
covered_area_m2 |
number | no | min 0.0; default 0.0
|
estimated_duration_s |
number | no | min 0.0; default 0.0
|
native |
SpotNativeJob or null | no | |
pattern_chain |
array of string | yes | min items 1; max items 16 |
plan_hash |
string | yes | SHA-256 of the chain and the segments (spot_plan_hash); must match.; pattern ^[0-9a-f]{64}$
|
segments |
array of SpotSegment | yes | min items 1; max items 10000 |
The plan expressed as a native job of the mower: whole map areas and one pattern.
Present only when the chain is exactly one pattern the mower may run by itself (stripes, diagonal, checkerboard, edge_only, or border_fill with one of them) on map areas, so a mower without custom_paths can still execute it as an ordinary StartMow(area_ids, pattern).
| Field | Type | Required | Notes |
|---|---|---|---|
area_ids |
array of string | yes | min items 1 |
pattern |
object | yes | Settings in the form of StartMow.pattern (name, angle_deg, spacing_m, border_laps, order). |
A drawn spot: a closed ring of WGS84 [lat, lon] corners (first point not repeated).
| Field | Type | Required | Notes |
|---|---|---|---|
polygon_wgs84 |
array of array of any | yes | min items 3; max items 64 |
One part of a spot plan: drive along path with the blades on or off (backwards with reverse: the mower faces against the direction of travel, part of a three-point turn).
| Field | Type | Required | Notes |
|---|---|---|---|
blades_on |
boolean | yes | |
kind |
"mow" | "turn" | "transfer"
|
no | default "mow"
|
path |
string | yes | Encoded polyline of local metres (x, y), centimetre precision (encode_polyline), at least two points.; min length 4; max length 200000 |
reverse |
boolean | no | Drive the polyline backwards (negative linear speed, the mower faces against the direction of travel); always with the blades off (ADR 0043).; default false
|
speed_mps |
number | yes | max 2.0; greater than 0.0 |
End the running spot run or drive calibration: zero frame, blades off, the mower stays where it is.
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"spot_stop" |
no | default "spot_stop"
|
Start mowing the given areas, a stored plan or an inline spot plan (exactly one).
| Field | Type | Required | Notes |
|---|---|---|---|
area_ids |
array of string | no | Map area ids to mow, in order. |
kind |
"start_mow" |
no | default "start_mow"
|
pattern |
object or null | no | Pattern settings (validated by the pattern's own JSON Schema). |
plan_ref |
string or null | no | Reference to a stored mowing plan. |
spot_plan |
SpotMowPlan or null | no | A route computed by the Planner (spot mowing). Runs only on mowers with custom_paths, or natively when the plan carries a native job. |
Read the mower's map again in full (areas, zones, paths, dock) and publish it. No motion; refused while a manual drive session is open (the transfer occupies the mower's command queue).
| Field | Type | Required | Notes |
|---|---|---|---|
kind |
"sync_map" |
no | default "sync_map"
|
A daily window in the mower's local time, HH:MM on a 24-hour clock. end before start crosses midnight (22:00 to 06:00).
| Field | Type | Required | Notes |
|---|---|---|---|
end |
string | yes | End, HH:MM (24-hour clock).; pattern `^([01]\d |
start |
string | yes | Start, HH:MM (24-hour clock).; pattern `^([01]\d |
How a spot run turns at the end of a lane (ADR 0043).
in_place: the mower rotates on the spot (fast, but an all-wheel-drive mower scuffs the turf). arc: a forward U-turn with a radius of at least half the lane spacing, or a bulb turn over the neighbouring lane when the spacing is narrower than the turning radius. multi_point: a three-point turn (forward arc, reverse arc with the blades off, forward arc); needs a drive link that can reverse (MowerCapabilities.drive_reverse).
Type: "in_place" | "arc" | "multi_point"
| Field | Type | Required | Notes |
|---|---|---|---|
ctx |
object | no | |
input |
any | no | |
loc |
array of string or integer | yes | |
msg |
string | yes | |
type |
string | yes |
Mirrored from docs/reference/api/fleet.md at commit 11a94afbcace55924c9675ef400e93c7785b4ac5. Edit the file in the repository, not this wiki page.
Mirrored from the docs/ directory at commit 11a94afbcace55924c9675ef400e93c7785b4ac5. Edit the files in the repository, not this wiki.
MowDeck documentation
- Home
- Phases
- Architecture
-
Decisions (ADR)
- Architecture decisions
- ADR 0001: OpenFGA instead of self-built authorization
- ADR 0002: Self-built Identity service in FastAPI instead of Keycloak or Zitadel
- ADR 0003: SvelteKit for the web app
- ADR 0004: Monorepo with a uv workspace
- ADR 0005: AGPL-3.0 for services and apps, Apache-2.0 for libraries
- ADR 0006: PostgreSQL for all persistence, no SQLite
- ADR 0007: NATS JetStream as event bus
- ADR 0008: Traefik as gateway
- ADR 0009: Command and event envelopes, subject naming and de-duplication
- ADR 0010: Python 3.13 for all services and libraries
- ADR 0011: Separate GPL-3.0 package for the PyMammotion adapter
- ADR 0012: Mower control interface and safety rules
- ADR 0013: Device-Gateway registry, sharding and per-mower concurrency
- ADR 0014: Authorization model, tuple ownership and the mowdeck-authz client
- ADR 0015: Tokens, sessions and key rotation
- ADR 0016: Fleet commands and authorization per command kind
- ADR 0017: Telemetry storage and retention
- ADR 0018: Realtime WebSocket protocol
- ADR 0019: Mammotion adapter transports, manual drive and secrets
- ADR 0020: Web app architecture
- ADR 0021: Browser authentication flow
- ADR 0022: Notifications: rules, recipients and delivery
- ADR 0023: Map rendering and projection
- ADR 0024: Scheduler: recurrence, rain pause and command issuing
- ADR 0025: Home Assistant integration as a pure API client
- ADR 0026: Manual drive channel over the Realtime WebSocket
- ADR 0027: Health history and theft alarm
- ADR 0028: Entitlements: plans as data and enforcement
- ADR 0029: Helm chart and release pipeline
- ADR 0030: Mowing patterns as plug-ins and the Planner
- ADR 0031: Billing with a Stripe adapter
- ADR 0032: Live camera over Agora, joined directly by the browser
- ADR 0033: Vision-assisted recovery with human approval
- ADR 0034: Linked cloud accounts and device discovery
- ADR 0035: Server-side camera frames and automatic AI analysis on errors
- ADR 0036: Native app shells with Capacitor, loading the web app from the server
- ADR 0037: Camera panorama calibration in the browser, with the AI supplying points only
- ADR 0038: Dual link per mower and firmware updates
- ADR 0039: Spot mowing by MowDeck-driven paths
- ADR 0040: Link heartbeat for online status
- ADR 0041: Spot runs from the dock: undock, transit and return
- ADR 0042: Drive calibration
- ADR 0043: Turn styles
- ADR 0044: Drive view with camera
- ADR 0045: Camera relay
- ADR 0046: Device settings as capabilities
- ADR 0047: The RTK base station as a Fleet device
- ADR 0048: Maintenance commands
- ADR 0049: Manual driving over the Mammotion cloud
- ADR 0050: Passkeys and the app login hand-off
- ADR 0051: Sign in with GitHub
- ADR 0052: Sign in with Apple
- ADR 0053: Retention and downsampling of the position track
- ADR 0054: Aerial photo under the mower map
- ADR 0055: Deploy maintenance window
- ADR 0056: Camera photo in push notifications for errors and theft alarms
- ADR 0057: Step-up re-authentication for critical actions
- ADR 0058: Theft tracking mode
- ADR 0059: iOS widgets and the mowing Live Activity
- ADR 0060: Apple Watch app
- ADR 0061: Mowing angle rotation
- ADR 0062: Setup tour for new users
- ADR 0063: Matter server (mowers in Apple Home and Google Home)
- ADR 0064: Personal access tokens and the public API documentation
- Development
-
Operations
- Operating the Compose stack
- Operating MowDeck on Kubernetes (Helm)
- Building the Bluetooth bridge (ESPHome on a XIAO ESP32-S3)
- Releases
- Billing operations
- Telemetry: retention and position downsampling
- iPhone and Android apps
- Passkeys
- Sign in with GitHub
- Aerial photo under the map
- Sign in with Apple
- Theft tracking mode
- Matter server
- Source code offer (AGPL-3.0 section 13)
- Spikes
- Guides
- API reference
- Original plan (German)