Repository navigation
Reference Notifications
Inbox, rules, channels and push devices.
Base path /api/v1/notifications behind the gateway. Authentication, rate limits and the error format are the same for every service: see Scripting MowDeck. Rendered from apps/web/openapi/notifications.json (OpenAPI 3.1), which you can also load into any OpenAPI tool.
Get Inbox
The caller's newest notifications, newest first.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
limit |
query | integer | no | min 1; max 200; default 50
|
unread |
query | boolean | no | Only unread notifications.; default false
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json Inbox
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Acknowledge
Acknowledge one of the caller's notifications: read plus acknowledged (idempotent; 404 for any other id). For a theft alarm, repeats of it (same kind and mower) are silenced for the caller for an hour (NOTIFICATIONS_ACK_SILENCE_SECONDS).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
notification_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json InboxItemOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Inbox Image
The camera photo of one of the caller's error or theft notifications (404 when there is none: not taken, expired after a day, or not the caller's notification).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
notification_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
image/jpeg any, image/png any |
| 422 | Validation Error |
application/json HTTPValidationError
|
Mark Read
Mark one of the caller's notifications read (idempotent; 404 for any other id).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
notification_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json InboxItemOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Put Live Activity Device
Register what the caller's app installation offers (ADR 0059): the push-to-start token for Live Activities and whether it has widgets. Replaces the earlier registration.
Request body (required): application/json LiveActivityDeviceIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LiveActivityDeviceOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Live Activity Device
Forget the caller's installation and its activities (logout; 404 for any other id).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
installation_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Put Live Activity
The app started a Live Activity for the mower: its update token (the server updates and ends the activity with it). 404 when the caller cannot view the mower.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes |
Request body (required): application/json LiveActivityIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LiveActivityOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Live Activity
The user ended the activity on the device: the server does not restart it during this job and sends it no more updates.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
mower_id |
path | string (uuid) | yes | |
installation_id |
query | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Apns Devices
The caller's iOS devices, oldest first.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ApnsDeviceList
|
Add Apns Device
Register the iOS app's APNs device token for the caller (plan feature notifications.push); the same token again replaces the earlier owner and name, and a new token of a known installation_id replaces that installation's earlier token.
Request body (required): application/json ApnsDeviceIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json ApnsDeviceOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Apns Device
Delete one of the caller's iOS devices (the app calls it on logout; 404 for any other id).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
device_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Ntfy
The caller's ntfy target (404 when none is configured).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json NtfyOut
|
Put Ntfy
Set the caller's ntfy target (the server must be on the allow list).
Request body (required): application/json NtfyIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json NtfyOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Ntfy
Remove the caller's ntfy target.
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
Get Preferences
The caller's preferences (defaults until saved: every mower, the default kinds).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PreferencesOut
|
Put Preferences
Replace the caller's preferences; a mower the caller cannot view is 404.
Request body (required): application/json PreferencesBody
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PreferencesOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get Push Image
The photo behind a push notification, for the iOS app's Notification Service Extension.
No login: the signed, short-lived URL in the push payload is the credential (it names one notification and expires after ten minutes). Rate limited. The photo is also in the caller's inbox for a day (GET /inbox/{id}/image).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
notification_id |
path | string (uuid) | yes | |
e |
query | integer | yes | Expiry, Unix seconds.; min 0 |
s |
query | string | yes | Signature.; min length 16; max length 64 |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
image/jpeg any, image/png any |
| 404 | Bad link, or the photo is not ready yet (try again). | no body |
| 410 | The link expired, or no photo was taken. | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Push Subscriptions
The caller's browser subscriptions.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PushSubscriptionList
|
Add Push Subscription
Store the browser's PushSubscription.toJSON() for the caller (plan feature notifications.push).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
user-agent |
header | string or null | no |
Request body (required): application/json PushSubscriptionIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json PushSubscriptionOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Push Subscription
Delete one of the caller's subscriptions (404 for any other id).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
subscription_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Vapid Public Key
The applicationServerKey (public, no token); 404 when Web Push is not configured.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json VapidPublicKey
|
Send Test
Send a test notification over every configured channel of the caller (rate limited).
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json TestSent
|
The iOS app's APNs device token (from didRegisterForRemoteNotificationsWithDeviceToken, hex encoded).
| Field | Type | Required | Notes |
|---|---|---|---|
device_name |
string or null | no | Shown in the list. |
installation_id |
string (uuid) or null | no | Stable id of the app installation (a UUID the iOS shell keeps in the Keychain). A new token of the same installation replaces the earlier one, so a device never holds two registrations. Without it (older app builds) each token is its own device. |
token |
string | yes | Device token in hexadecimal (case-insensitive, stored in lower case).; min length 64; max length 200; pattern ^[0-9a-fA-F]+$
|
The user's iOS devices, oldest first.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of ApnsDeviceOut | yes |
A registered iOS device; the token itself (a capability) is not echoed.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
device_name |
string or null | yes | |
id |
string (uuid) | yes | |
token_suffix |
string | yes | The last 8 hex characters of the token. |
| Field | Type | Required | Notes |
|---|---|---|---|
detail |
array of ValidationError | no |
The newest notifications, newest first.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of InboxItemOut | yes | |
unread |
integer | yes |
One notification of the user.
| Field | Type | Required | Notes |
|---|---|---|---|
acked |
boolean | no | Acknowledged by the user (alarms).; default false
|
acked_at |
string (date-time) or null | no | |
body |
string | yes | |
created_at |
string (date-time) | yes | |
has_image |
boolean | no | A camera photo was taken for this error or theft event and is still kept (a day): GET /api/v1/notifications/inbox/{id}/image returns it.; default false
|
id |
string (uuid) | yes | |
kind |
NotificationKind | yes | |
mower_id |
string (uuid) or null | yes | |
occurred_at |
string (date-time) | yes | |
read |
boolean | yes | |
read_at |
string (date-time) or null | yes | |
severity |
NotificationSeverity | yes | |
title |
string | yes | |
url |
string or null | yes |
What one app installation offers for Live Activities and widgets (ADR 0059).
| Field | Type | Required | Notes |
|---|---|---|---|
installation_id |
string (uuid) | yes | The installation id the iOS shell keeps in the Keychain (the same as for POST /me/push/apns). |
push_to_start_token |
string or null | no | ActivityKit push-to-start token (hex); null when the device has none (before iOS 17.2) or the user turned Live Activities off. |
widgets_enabled |
boolean | no | The installation has MowDeck widgets: reload them by push.; default false
|
The stored registration (the token, a capability, is not echoed).
| Field | Type | Required | Notes |
|---|---|---|---|
has_push_to_start_token |
boolean | yes | |
installation_id |
string (uuid) | yes | |
updated_at |
string (date-time) | yes | |
widgets_enabled |
boolean | yes |
A Live Activity the app started for a mower, with its update token.
| Field | Type | Required | Notes |
|---|---|---|---|
activity_id |
string | yes | min length 1; max length 100; pattern ^[A-Za-z0-9-]+$
|
installation_id |
string (uuid) | yes | |
push_token |
string | yes | The activity's push token (hex) the server updates it with.; min length 64; max length 200; pattern ^[0-9a-fA-F]+$
|
The stored activity (tokens are not echoed).
| Field | Type | Required | Notes |
|---|---|---|---|
activity_id |
string or null | yes | |
installation_id |
string (uuid) | yes | |
mower_id |
string (uuid) | yes | |
started_at |
string (date-time) | yes | |
state |
string | yes |
What a notification is about.
Type: "mowing_finished" | "mower_stuck" | "battery_low" | "mower_offline" | "mower_online" | "job_started" | "mower_lifted" | "mower_left_dock_unexpectedly" | "geofence_exit" | "blade_maintenance" | "vision_proposal" | "vision_auto_proposal" | "firmware_update_available" | "firmware_update_finished" | "firmware_update_failed" | "tracking_started" | "tracking_moved" | "tracking_stale" | "tracking_ended" | "security_new_login" | "test"
How urgent a notification is; channels map it to TTL, urgency or priority.
Type: "info" | "warning" | "critical"
The user's ntfy target.
| Field | Type | Required | Notes |
|---|---|---|---|
server_url |
string | yes | max length 300 |
token |
string or null | no | Access token (tk_...), stored, never returned. Omitted or null keeps the stored token; an empty string removes it. |
topic |
string | yes | min length 1; max length 64 |
The stored ntfy target (without the token).
| Field | Type | Required | Notes |
|---|---|---|---|
has_token |
boolean | yes | |
server_url |
string | yes | |
topic |
string | yes | |
updated_at |
string (date-time) | yes |
What the user wants to be notified about (PUT replaces everything).
| Field | Type | Required | Notes |
|---|---|---|---|
all_mowers |
boolean | no | Follow every mower the user can view, now and later.; default false
|
channels |
array of string | no | Channels to use when a target is configured (webpush, ntfy, apns, ...).; max items 10 |
enabled_kinds |
array of NotificationKind | yes | Kinds to notify; job_started is off by default.; max items 20 |
language |
string | no | max length 8; default "en"
|
mower_ids |
array of string (uuid) | no | Followed mowers when all_mowers is false (each must be viewable, else 404).; max items 1000 |
quiet_hours |
QuietHoursBody or null | no | |
timezone |
string | no | max length 64; default "UTC"
|
Stored preferences (or the defaults) plus what can be chosen.
| Field | Type | Required | Notes |
|---|---|---|---|
all_mowers |
boolean | yes | |
available_channels |
array of string | yes | Channels configured on this server. |
available_kinds |
array of NotificationKind | yes | |
channels |
array of string | yes | |
enabled_kinds |
array of NotificationKind | yes | |
language |
string | yes | |
languages |
array of string | yes | |
mower_ids |
array of string (uuid) | yes | |
quiet_hours |
QuietHoursBody or null | yes | |
stored |
boolean | yes | False until the user saved preferences once. |
timezone |
string | yes |
PushSubscription.toJSON().keys.
| Field | Type | Required | Notes |
|---|---|---|---|
auth |
string | yes | min length 1; max length 64 |
p256dh |
string | yes | min length 1; max length 128 |
The browser's PushSubscription.toJSON() (expirationTime is ignored).
| Field | Type | Required | Notes |
|---|---|---|---|
endpoint |
string | yes | min length 10; max length 2000 |
keys |
PushKeys | yes |
The user's subscriptions.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of PushSubscriptionOut | yes |
A stored subscription; the endpoint itself (a capability URL) is not echoed.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
endpoint_host |
string | yes | |
id |
string (uuid) | yes | |
user_agent |
string or null | yes |
A daily window (local time of timezone) without pushes; may cross midnight.
| Field | Type | Required | Notes |
|---|---|---|---|
end |
string | yes | pattern `^([01]\d |
start |
string | yes | pattern `^([01]\d |
Answer of POST /test.
| Field | Type | Required | Notes |
|---|---|---|---|
body |
string | yes | |
channels |
array of string | yes | Channels a delivery was queued for. |
notification_id |
string (uuid) | yes | |
title |
string | yes |
| Field | Type | Required | Notes |
|---|---|---|---|
ctx |
object | no | |
input |
any | no | |
loc |
array of string or integer | yes | |
msg |
string | yes | |
type |
string | yes |
The applicationServerKey for pushManager.subscribe.
| Field | Type | Required | Notes |
|---|---|---|---|
public_key |
string | yes |
Mirrored from docs/reference/api/notifications.md at commit 14af01c2a57ec5adc34136f7375ca93f2a5b7226. Edit the file in the repository, not this wiki page.
Mirrored from the docs/ directory at commit 14af01c2a57ec5adc34136f7375ca93f2a5b7226. 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
- ADR 0065: Security center and new-login alerts
- ADR 0066: Cloud provider plugins and adapters for more vendors
- ADR 0067: Error code lexicon, provider independent
- ADR 0068: Public demo mode
-
Development
- Getting started
- Service template
- Shared libraries
- Cloud providers: adding a vendor
- Adding an error lexicon for a vendor
- Design: identity and authorization
- Design: fleet, telemetry, realtime
- Design: web app
- Web app
- Home Assistant integration
- Camera source bridge protocol
- Fuzzing and property-based tests
- GitHub wiki mirror
-
Operations
- Operating the Compose stack
- Operating MowDeck on Kubernetes (Helm)
- Building the Bluetooth bridge (ESPHome on a XIAO ESP32-S3)
- Releases
- Vendor library updates
- 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)
- Public demo
- Spikes
-
Guides
- Guides
- ESP32 bridge: purchase and setup
- Signing in with a passkey
- Signing in with GitHub
- Error codes in plain words
- Aerial photo under the map
- Signing in with Apple
- Confirming critical actions
- Your security page
- iPhone widgets and the mowing Live Activity
- Apple Watch
- The setup tour
- Apple Home and Google Home (Matter)
- Worx Landroid, Kress and LandXcape mowers
- Scripting MowDeck
- API reference
- Original plan (German)