Repository navigation
Reference Identity
Accounts, users, roles, sessions, API tokens and personal access tokens.
Base path /api/v1/identity behind the gateway. Authentication, rate limits and the error format are the same for every service: see Scripting MowDeck. Rendered from apps/web/openapi/identity.json (OpenAPI 3.1), which you can also load into any OpenAPI tool.
Get Account
The account (any member).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AccountOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Rename Account
Rename the account (can_manage_users).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
Request body (required): application/json AccountPatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AccountOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Account
Request deletion (owner): locked for the grace period. Needs the password in the body or, without it, a recent step-up confirmation.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
Request body: application/json AccountDeleteIn or null
| Status | Meaning | Body |
|---|---|---|
| 202 | Successful Response |
application/json AccountOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Tokens
API tokens of the account (without secrets).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of ApiTokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Create Token
Create an API token; the secret is in the response once. Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
Request body (required): application/json ApiTokenIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json ApiTokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Purge Revoked Tokens
Delete every revoked API token of the account for good; active tokens stay. Each one is audited (api_token.purged); the audit history of the tokens stays.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ApiTokensPurgedOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Revoke Token
Revoke an API token; with purge=true delete an already revoked one for good.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
token_id |
path | string (uuid) | yes | |
purge |
query | boolean | no | Delete the revoked token for good instead of revoking it; 409 while the token is not revoked; default false
|
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Audit
Audit log of the account, newest first; page with before_id.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
action |
query | string or null | no | |
actor |
query | string or null | no | |
target_id |
query | string or null | no | |
since |
query | string (date-time) or null | no | |
before_id |
query | integer or null | no | |
limit |
query | integer | no | min 1; max 200; default 50
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of AuditOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Permissions
The permission catalogue (what roles and tokens can contain).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of PermissionOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Reconcile
Repair OpenFGA from the database for every subject of the account.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json ReconcileOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Restore Account
Undo a deletion request within the grace period (owner).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AccountOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List Assignments
Assignments of the account (own ones for members without can_manage_users).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
subject_id |
query | string (uuid) or null | no |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of RoleAssignmentOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Assign Role
Assign a role at a level; writes the expanded grant tuples. Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
Request body (required): application/json RoleAssignmentIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json RoleAssignmentOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Unassign Role
Remove an assignment; the subject's tuples are reconciled. Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
assignment_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Roles
Roles of the account.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of RoleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Create Role
A custom role (never more than the actor holds).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
Request body (required): application/json RoleIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json RoleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Update Role
Change a role; every holder is reconciled. Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
role_id |
path | string (uuid) | yes |
Request body (required): application/json RolePatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json RoleOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete Role
Delete an unassigned custom or default role.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
role_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
List Users
Members and sub-users.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of MemberOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Create User
Create a sub-user, optionally with roles at levels (anti-escalation applies). Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes |
Request body (required): application/json SubUserIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json MemberOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Get User
A member (yourself, or anybody with can_manage_users).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MemberOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Rename User
Change the display name of a sub-user.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
Request body (required): application/json UserPatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MemberOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Delete User
Delete a sub-user, or remove a person from the account. Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Disable User
Disable: sessions end, the user's API tokens are revoked, tuples are removed.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MemberOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Enable User
Enable again (revoked API tokens stay revoked).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MemberOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
List User Passkeys
Passkeys of a sub-user of this account (persons manage their own: 403).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of PasskeyOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Remove User Passkey
Remove a passkey of a sub-user of this account (its password stays). Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes | |
passkey_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Set Password
Set a temporary password of a sub-user (must be changed at the next login). Step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
account_id |
path | string (uuid) | yes | |
user_id |
path | string (uuid) | yes |
Request body (required): application/json PasswordSetIn
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Demo Session
"Try the demo": a session of the prepared demo user without credentials (the same tokens and cookie as POST /session). 404 outside demo mode and while the demo is not seeded; rate limited per address.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
X-Mowdeck-Refresh |
header | string or null | no |
cookie-only: the refresh token is only set as the HttpOnly cookie and refresh_token in the body is null (browsers). Without it the body carries it too. |
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
My External Identities
The caller's linked accounts of login providers.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of ExternalIdentityOut
|
Unlink External Identity
Remove the caller's link to a login provider (the password stays). Step-up: a stolen session must not be able to strip the owner's ways in unnoticed.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
provider |
path | string | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Link External Identity
Start linking an account of a login provider to the caller: the current password again (the login limits apply) or, without it, a recent step-up confirmation, then the provider's authorization URL and the binding cookie. 409 when an account of this provider is already linked.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
provider |
path | string | yes |
Request body (required): application/json ExternalLinkIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json OAuthStartOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Oauth Callback
The provider sends the browser back here: finish the sign-in (refresh cookie as after a password login) or the link, then redirect to the web app (303).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
provider |
path | string | yes | |
mowdeck_oauth |
cookie | string or null | no |
| Status | Meaning | Body |
|---|---|---|
| 303 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Oauth Start
Start signing in with a login provider (404 when it is not enabled): its authorization URL, and a cookie that binds the round trip to this browser.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
provider |
path | string | yes |
Request body: application/json OAuthStartIn or null
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json OAuthStartOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Login Methods
Which login methods the installation offers (public; the login page asks).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json LoginMethodsOut
|
My Passkeys
The caller's passkeys, newest first.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of PasskeyOut
|
Add Passkey
Finish adding a passkey (audited as passkey.added).
Request body (required): application/json PasskeyRegistrationIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json PasskeyOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Passkey Registration Options
Start adding a passkey: the current password again, then options for navigator.credentials.create() (discoverable, user verification required).
Request body (required): application/json PasskeyRegistrationOptionsIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PasskeyOptionsOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Rename Passkey
Rename one of the caller's passkeys.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
passkey_id |
path | string (uuid) | yes |
Request body (required): application/json PasskeyPatch
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PasskeyOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Remove Passkey
Remove one of the caller's passkeys; the password always stays. Needs a recent confirmation (step-up).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
passkey_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Step Up Passkey
Confirm a critical action with one of the caller's passkeys: a new access token.
Request body (required): application/json StepUpPasskeyIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Step Up Passkey Options
Options for navigator.credentials.get() to confirm with a passkey (user verification required).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PasskeyOptionsOut
|
Step Up Password
Confirm a critical action with the current password: a new access token with a fresh auth_time. The login limits apply; a wrong password is a failed login of the user.
Request body (required): application/json StepUpPasswordIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Passkey Challenge
Start a passwordless login: options for navigator.credentials.get() with user verification required and no allowCredentials (discoverable credentials).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PasskeyOptionsOut
|
Passkey Login
Finish a passwordless login: the same tokens and cookie as POST /session.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
X-Mowdeck-Refresh |
header | string or null | no |
cookie-only: the refresh token is only set as the HttpOnly cookie and refresh_token in the body is null (browsers). Without it the body carries it too. |
Request body (required): application/json PasskeyLoginIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Platform Accounts
Every account of the installation (operator admins; no mower data).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
offset |
query | integer | no | min 0; default 0
|
limit |
query | integer | no | min 1; max 200; default 50
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json PlatformAccountPageOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Security Overview
Password status, the new-login alert setting and how many passkeys, linked providers, personal access tokens, sessions and known devices the caller has.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json SecurityOverviewOut
|
My Security Events
The caller's own security events of the last days (default 30), newest first: logins and failed logins, new devices, passkeys, linked providers, password changes, personal access tokens, ended sessions. Addresses are shortened to their network.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
days |
query | integer | no | min 1; max 90; default 30
|
limit |
query | integer | no | min 1; max 200; default 100
|
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of SecurityEventOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Set Security Alerts
Turn the notification about a login from a new device on or off. Turning it off needs a recent step-up (401 reauth-required): a stolen session must not silence it.
Request body (required): application/json SecurityAlertsIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json SecurityAlertsOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
My Sessions
The caller's live login sessions (browsers and app installations, all accounts), the current one first (current), then by last use.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of SessionOut
|
Revoke Other Sessions
Sign out everywhere else: every login session of the caller except this one ends (as DELETE /me/sessions/{id} does for one). Needs a recent step-up.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json SessionsRevokedOut
|
Revoke Session
End one of the caller's login sessions: its refresh token fails at once, its access tokens are refused by Identity at once and by the other services when they expire (at most 10 minutes). Idempotent; 404 for any other session. Needs a recent step-up.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
session_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Jwks Document
The public signing keys (RFC 7517).
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json object |
App Login Code
Native app hand-off (ADR 0050), browser side: exchange the caller's fresh login session (any login method, at most a few minutes old) for a one-time code bound to the app's sign-in request and its PKCE challenge (403 for an unknown, used or expired request). The browser session ends; the page sends the code to the app's URL scheme.
Request body (required): application/json AppCodeIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AppCodeOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
App Login Session
Native app hand-off, app side: the one-time code and the PKCE verifier give the app a normal session (the same tokens and cookie as POST /session). The code is single use.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
X-Mowdeck-Refresh |
header | string or null | no |
cookie-only: the refresh token is only set as the HttpOnly cookie and refresh_token in the body is null (browsers). Without it the body carries it too. |
Request body (required): application/json AppSessionIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
App Login Start
Native app hand-off (ADR 0050), first step in the app: register the S256 hash of the PKCE verifier; the sign-in page in the system browser gets only the request id.
Request body (required): application/json AppLoginStartIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json AppLoginStartOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Me
The caller: claims of the current token, user data and memberships.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MeOut
|
List Personal Tokens
The caller's personal access tokens (ADR 0064), newest first, without secrets. Users only: an API token gets 403, so a token never sees or manages tokens.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of PersonalTokenOut
|
Create Personal Token
Create a personal access token for your own scripts: curated scopes, an expiry of at most 365 days, at most 25 active per user. Needs a recent step-up (ADR 0057): without it 401 reauth-required; API tokens get 403. The secret is in the response once.
Request body (required): application/json PersonalTokenIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json PersonalTokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Revoke Personal Token
Revoke one of your personal access tokens at once (404 for any other token).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
token_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
My Onboarding
The caller's progress through the setup tour of the web app (ADR 0062): status, skipped steps and dismissed hints. new (nothing stored) for a user who never saw the tour. Only users; API tokens get 403.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json OnboardingOut
|
Save Onboarding
Replace the caller's tour progress (status, skipped steps, dismissed hints). The keys are the web app's (^[a-z][a-z0-9-]{0,31}$, at most 32 each, duplicates dropped).
Request body (required): application/json OnboardingIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json OnboardingOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Change Password
Change the own password; the other sessions end.
Request body (required): application/json PasswordChangeIn
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
My Permissions
Batch of "may I?" questions for rendering the UI (answers are not cached here).
Request body (required): application/json PermissionsIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of boolean |
| 422 | Validation Error |
application/json HTTPValidationError
|
My Platform
Whether the caller is an operator admin; 200 for every authenticated principal.
Lets the web app decide about the operator console without probing a 403 endpoint. The check goes through the authorizer and its cache.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json MePlatformOut
|
List Widget Credentials
The caller's iOS widget credentials (ADR 0059), newest first, without secrets.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of WidgetCredentialOut
|
Create Widget Credential
Create the credential the iOS widgets and the Live Activity use instead of the app's session: an API token limited to mower.view and mower.control on the account (as far as the caller holds them), valid for 90 days, revocable here and in the token list. The secret is in the response once. Only users (not API tokens) can call it.
Request body (required): application/json WidgetCredentialIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json WidgetCredentialOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Revoke Widget Credential
Revoke one of the caller's widget credentials (404 for any other token).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
token_id |
path | string (uuid) | yes |
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Register
Create an account; the registering user becomes its owner.
Request body (required): application/json RegisterIn
| Status | Meaning | Body |
|---|---|---|
| 201 | Successful Response |
application/json RegisteredOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Login
Log in with username and password: access token, refresh token (cookie, and the body unless X-Mowdeck-Refresh: cookie-only).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
X-Mowdeck-Refresh |
header | string or null | no |
cookie-only: the refresh token is only set as the HttpOnly cookie and refresh_token in the body is null (browsers). Without it the body carries it too. |
Request body (required): application/json LoginIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Logout
End the login session of the refresh token.
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
X-Requested-With |
header | string or null | no | |
mowdeck_refresh |
cookie | string or null | no |
Request body: application/json RefreshIn or null
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
| 422 | Validation Error |
application/json HTTPValidationError
|
Logout All
End every session of the calling user.
| Status | Meaning | Body |
|---|---|---|
| 204 | Successful Response | no body |
Refresh
Rotate the refresh token; a reused token ends the whole login session (except within the short grace after a lost response).
| Parameter | In | Type | Required | Notes |
|---|---|---|---|---|
X-Requested-With |
header | string or null | no | |
X-Mowdeck-Refresh |
header | string or null | no |
cookie-only: the refresh token is only set as the HttpOnly cookie and refresh_token in the body is null (browsers). Without it the body carries it too. |
mowdeck_refresh |
cookie | string or null | no |
Request body: application/json RefreshIn or null
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Exchange
Exchange an API token for a 10 minute access token (kind=api_token).
Request body (required): application/json TokenExchangeIn
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json TokenOut
|
| 422 | Validation Error |
application/json HTTPValidationError
|
Ui Areas
Areas of the web app shell that the deployed modules announce and the caller may open.
Merged from the module descriptors Identity polls (MOWDECK_IDENTITY_MODULE_URLS) and its own; an area is listed when its required_permission is among the caller's permissions.
| Status | Meaning | Body |
|---|---|---|
| 200 | Successful Response |
application/json array of UiAreaOut
|
DELETE /accounts/{id}: the owner's password, or none after a step-up confirmation.
| Field | Type | Required | Notes |
|---|---|---|---|
password |
string or null | no |
What an account is.
Type: "household" | "business"
An account.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
delete_after |
string (date-time) or null | yes | |
id |
string (uuid) | yes | |
kind |
string | yes | |
name |
string | yes | |
plan |
string | yes | |
slug |
string | yes | |
status |
string | yes |
PATCH /accounts/{id}.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | yes | min length 1; max length 200 |
POST /api-tokens.
| Field | Type | Required | Notes |
|---|---|---|---|
expires_at |
string (date-time) or null | no | |
grants |
array of TokenGrantIn | yes | min items 1; max items 50 |
name |
string | yes | min length 1; max length 100 |
An API token (never with its secret, except once at creation).
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
created_by |
string (uuid) | yes | |
expires_at |
string (date-time) or null | yes | |
grants |
array of object | yes | |
id |
string (uuid) | yes | |
last_used_at |
string (date-time) or null | yes | |
name |
string | yes | |
permissions |
array of string | yes | |
prefix |
string | yes | |
purpose |
TokenPurpose | yes |
integration (created by an admin) or personal (a user's own personal access token, ADR 0064) |
revoked_at |
string (date-time) or null | yes | |
token |
string or null | no | The secret, returned only at creation |
Revoked API tokens deleted for good.
| Field | Type | Required | Notes |
|---|---|---|---|
deleted |
integer | yes | How many revoked tokens were deleted |
ids |
array of string (uuid) | yes | Ids of the deleted tokens |
POST /app-login/code: hand the fresh browser login to the native app.
| Field | Type | Required | Notes |
|---|---|---|---|
request_id |
string (uuid) | yes | The app's sign-in request (from /app-login/start) |
A one-time code for the native app (redeemed with the verifier, valid for seconds).
| Field | Type | Required | Notes |
|---|---|---|---|
code |
string | yes | |
expires_in |
integer | yes |
POST /app-login/start: the native app registers its PKCE challenge.
| Field | Type | Required | Notes |
|---|---|---|---|
code_challenge |
string | yes | PKCE S256 challenge of the app: BASE64URL(SHA256(code_verifier)); pattern ^[A-Za-z0-9_-]{43}$
|
The app's sign-in request: its id goes into the sign-in page's address.
| Field | Type | Required | Notes |
|---|---|---|---|
expires_in |
integer | yes | |
request_id |
string (uuid) | yes |
POST /app-login/session: the app redeems its code with the PKCE verifier.
| Field | Type | Required | Notes |
|---|---|---|---|
code |
string | yes | min length 1; max length 100 |
code_verifier |
string | yes | min length 43; max length 128 |
A role at a level (inside POST /users).
| Field | Type | Required | Notes |
|---|---|---|---|
level |
LevelIn | yes | |
role_id |
string (uuid) | yes |
An audit entry.
| Field | Type | Required | Notes |
|---|---|---|---|
action |
string | yes | |
actor_kind |
string or null | yes | |
actor_name |
string or null | yes | |
actor_subject |
string or null | yes | |
at |
string (date-time) | yes | |
correlation_id |
string or null | yes | |
details |
object | yes | |
id |
integer | yes | |
ip |
string or null | yes | |
outcome |
string | yes | |
target_id |
string or null | yes | |
target_type |
string or null | yes |
A linked account of a login provider (never the provider's settings).
| Field | Type | Required | Notes |
|---|---|---|---|
display_name |
string or null | yes | The account's name at the provider (login) |
last_used_at |
string (date-time) or null | yes | |
linked_at |
string (date-time) | yes | |
provider |
string | yes |
POST /me/external-identities/{provider}/link: the current password again, or none after a step-up confirmation.
| Field | Type | Required | Notes |
|---|---|---|---|
password |
string or null | no |
| Field | Type | Required | Notes |
|---|---|---|---|
detail |
array of ValidationError | no |
A level: {"type": "group", "id": "<uuid>"}.
| Field | Type | Required | Notes |
|---|---|---|---|
id |
string (uuid) | yes | |
type |
LevelType | yes |
A level.
| Field | Type | Required | Notes |
|---|---|---|---|
id |
string (uuid) | yes | |
type |
string | yes |
Where a right is granted; it applies to everything below.
Type: "account" | "site" | "group" | "mower"
POST /session.
| Field | Type | Required | Notes |
|---|---|---|---|
account_id |
string (uuid) or null | no | Account to act for (default: own) |
password |
string | yes | min length 1; max length 256 |
username |
string | yes | min length 1; max length 64 |
Login methods this installation offers (the login page shows what is on).
| Field | Type | Required | Notes |
|---|---|---|---|
apple |
boolean | no | Sign in with Apple is configured (only this flag; the Apple settings are never published); default false
|
github |
boolean | no | Sign in with GitHub is configured (only this flag; the GitHub settings are never published); default false
|
passkey |
boolean | yes | Passkeys are configured (MOWDECK_IDENTITY_PUBLIC_URL) |
password |
boolean | no | default true
|
A member of the account.
| Field | Type | Required | Notes |
|---|---|---|---|
assignments |
array of RoleAssignmentOut | yes | |
created_at |
string (date-time) | yes | |
display_name |
string | yes | |
email |
string or null | yes | |
id |
string (uuid) | yes | |
is_admin |
boolean | yes | |
is_owner |
boolean | yes | |
kind |
string | yes | |
last_login_at |
string (date-time) or null | yes | |
membership_status |
string | yes | |
must_change_password |
boolean | yes | |
status |
string | yes | |
subuser |
boolean | yes | |
username |
string | yes |
A membership in GET /me.
| Field | Type | Required | Notes |
|---|---|---|---|
account_id |
string (uuid) | yes | |
account_name |
string | yes | |
account_status |
string | yes | |
is_admin |
boolean | yes | |
is_owner |
boolean | yes | |
status |
string | yes |
GET /me.
| Field | Type | Required | Notes |
|---|---|---|---|
account_id |
string (uuid) or null | yes | |
display_name |
string or null | yes | |
email |
string or null | no | |
kind |
string | yes | |
memberships |
array of MembershipOut | no | |
must_change_password |
boolean | no | default false
|
permissions |
array of string | yes | |
plan |
string or null | yes | |
roles |
array of string | yes | |
session_id |
string (uuid) or null | yes | |
subject |
string (uuid) | yes | |
username |
string or null | no |
The caller's role on the platform (operator console).
| Field | Type | Required | Notes |
|---|---|---|---|
operator_admin |
boolean | yes | True when the caller holds platform:main#operator_admin in OpenFGA. |
POST /oauth/{provider}/start: the sign-in page's query to come back to.
| Field | Type | Required | Notes |
|---|---|---|---|
return_query |
string or null | no | Query of /login to return to; only next (a local path), app_request and app_state are kept |
Where to send the browser for the provider's sign-in (the browser keeps a cookie that binds the round trip to it).
| Field | Type | Required | Notes |
|---|---|---|---|
authorize_url |
string | yes | |
expires_in |
integer | yes | Seconds the round trip stays usable |
PUT /me/onboarding: the whole state, replacing the stored one.
| Field | Type | Required | Notes |
|---|---|---|---|
dismissed_hints |
array of string | no | max items 32 |
skipped_steps |
array of string | no | max items 32 |
status |
"active" | "dismissed" | "completed"
|
yes |
active, dismissed or completed (new cannot be stored). |
The caller's progress through the setup tour (ADR 0062). Whether a step is done is not here: the web app reads that from the real state.
| Field | Type | Required | Notes |
|---|---|---|---|
dismissed_hints |
array of string | yes | Keys of the "first time here" hints the user dismissed. |
skipped_steps |
array of string | yes | Keys of the steps the user skipped. |
status |
"new" | "active" | "dismissed" | "completed"
|
yes |
new: never decided (nothing stored yet); active: the tour runs; dismissed: closed without finishing; completed: every step done or skipped. |
updated_at |
string (date-time) or null | yes | Last change; null while new. |
POST /passkeys/session: the answer to a login challenge.
| Field | Type | Required | Notes |
|---|---|---|---|
account_id |
string (uuid) or null | no | Account to act for (default: own) |
ceremony_id |
string (uuid) | yes | |
credential |
object | yes | The PublicKeyCredential as JSON (PublicKeyCredential.toJSON(): id, rawId, type, response with base64url fields, clientExtensionResults) |
Options of a WebAuthn ceremony and the id that answers them.
| Field | Type | Required | Notes |
|---|---|---|---|
ceremony_id |
string (uuid) | yes | |
public_key |
object | yes | PublicKeyCredentialCreationOptions or ...RequestOptions as JSON (base64url binary fields), for PublicKeyCredential.parseCreationOptionsFromJSON / parseRequestOptionsFromJSON |
A passkey (never with its public key or credential id).
| Field | Type | Required | Notes |
|---|---|---|---|
aaguid |
string or null | yes | Model of the authenticator, if it told |
backed_up |
boolean | yes | Synced as of the last use |
created_at |
string (date-time) | yes | |
id |
string (uuid) | yes | |
last_used_at |
string (date-time) or null | yes | |
name |
string | yes | |
synced |
boolean | yes | A multi-device passkey that may be synced (backup eligible) |
transports |
array of string | yes | |
user_agent |
string or null | yes | Browser of the registration (a device hint) |
PATCH /me/passkeys/{id}.
| Field | Type | Required | Notes |
|---|---|---|---|
name |
string | yes | min length 1; max length 64 |
POST /me/passkeys: the new credential.
| Field | Type | Required | Notes |
|---|---|---|---|
ceremony_id |
string (uuid) | yes | |
credential |
object | yes | The PublicKeyCredential as JSON (PublicKeyCredential.toJSON(): id, rawId, type, response with base64url fields, clientExtensionResults) |
name |
string or null | no |
POST /me/passkeys/options: the current password (re-authentication), or none after a step-up confirmation.
| Field | Type | Required | Notes |
|---|---|---|---|
password |
string or null | no |
PUT /me/password.
| Field | Type | Required | Notes |
|---|---|---|---|
current_password |
string | yes | min length 1; max length 256 |
new_password |
string | yes | min length 1; max length 256 |
POST /users/{id}/password: a temporary password for a sub-user.
| Field | Type | Required | Notes |
|---|---|---|---|
password |
string | yes | min length 1; max length 256 |
A catalogue entry.
| Field | Type | Required | Notes |
|---|---|---|---|
api_tokens |
boolean | yes | |
description |
string | yes | |
implied_by |
array of string | yes | |
in_model |
boolean | yes | |
key |
string | yes | |
levels |
array of string | yes | |
module |
string | yes |
One question of POST /me/permissions.
| Field | Type | Required | Notes |
|---|---|---|---|
object |
string | yes | pattern `^(account |
relation |
"can_view" | "can_control" | "can_drive" | "can_edit_schedule" | "can_bulk_command" | "can_manage_mowers" | "can_manage_users" | "can_manage_billing" | "can_view_audit" | "can_manage_account" | "can_emergency_stop" | "member"
|
yes |
POST /me/permissions: up to 100 questions.
| Field | Type | Required | Notes |
|---|---|---|---|
checks |
array of PermissionQuery | yes | max items 100 |
POST /me/api-tokens: a personal access token for the caller's own scripts.
| Field | Type | Required | Notes |
|---|---|---|---|
expires_in_days |
integer | yes | The token stops working after this many days.; min 1.0; max 365.0 |
level |
LevelIn or null | no | Where the scopes apply; default the whole account (a site, group or mower of the account limits the token to it). |
name |
string | yes | min length 1; max length 100 |
scopes |
array of string | yes | From mower.view (read state, telemetry, history, realtime), mower.control (start, pause, resume, dock) and schedule.edit; mower.view is required with any other. Each must be held by the caller on level.; min items 1; max items 3 |
A personal access token (never with its secret, except once at creation).
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
expires_at |
string (date-time) | yes | |
id |
string (uuid) | yes | |
last_used_at |
string (date-time) or null | yes | Last exchange for an access token (updated at most every few minutes) |
level |
LevelOut | yes | |
name |
string | yes | |
prefix |
string | yes | The first characters of the secret, to recognise it |
revoked_at |
string (date-time) or null | yes | |
scopes |
array of string | yes | |
token |
string or null | no | The secret (mdk_...), returned only at creation. Exchange it at POST /api/v1/identity/token for 10 minute access tokens. |
An account for operators.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
id |
string (uuid) | yes | |
kind |
string | yes | |
name |
string | yes | |
owner_username |
string or null | yes | |
status |
string | yes |
A page of accounts (offset/limit), oldest first.
| Field | Type | Required | Notes |
|---|---|---|---|
items |
array of PlatformAccountOut | yes | |
limit |
integer | yes | |
offset |
integer | yes | |
total |
integer | yes |
What a reconcile changed in OpenFGA.
| Field | Type | Required | Notes |
|---|---|---|---|
changed_subjects |
array of string | yes | |
deletes |
integer | yes | |
writes |
integer | yes |
POST /session/refresh and /session/logout; the cookie may be used instead.
| Field | Type | Required | Notes |
|---|---|---|---|
refresh_token |
string or null | no |
The new account and its owner.
| Field | Type | Required | Notes |
|---|---|---|---|
account_id |
string (uuid) | yes | |
user_id |
string (uuid) | yes |
POST /register.
| Field | Type | Required | Notes |
|---|---|---|---|
account_kind |
AccountKind | no | default "household"
|
account_name |
string | yes | min length 1; max length 200 |
display_name |
string or null | no | |
email |
string or null | no | |
password |
string | yes | min length 1; max length 256 |
username |
string | yes | min length 1; max length 64 |
POST /role-assignments.
| Field | Type | Required | Notes |
|---|---|---|---|
level |
LevelIn | yes | |
role_id |
string (uuid) | yes | |
subject_id |
string (uuid) | yes | |
subject_type |
"user" |
no | default "user"
|
An assignment.
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
created_by |
string (uuid) or null | yes | |
id |
string (uuid) | yes | |
level |
LevelOut | yes | |
role_id |
string (uuid) | yes | |
subject_id |
string (uuid) | yes | |
subject_type |
string | yes |
POST /roles.
| Field | Type | Required | Notes |
|---|---|---|---|
description |
string | no | max length 500; default ""
|
name |
string | yes | min length 1; max length 100 |
permissions |
array of string | yes | max items 100 |
A role.
| Field | Type | Required | Notes |
|---|---|---|---|
description |
string | yes | |
editable |
boolean | yes | |
id |
string (uuid) | yes | |
key |
string | yes | |
kind |
string | yes | |
name |
string | yes | |
permissions |
array of string | yes |
PATCH /roles/{id}.
| Field | Type | Required | Notes |
|---|---|---|---|
description |
string or null | no | |
name |
string or null | no | |
permissions |
array of string or null | no |
PUT /me/security/alerts.
| Field | Type | Required | Notes |
|---|---|---|---|
new_login_alerts |
boolean | yes |
The alert setting after the change.
| Field | Type | Required | Notes |
|---|---|---|---|
new_login_alerts |
boolean | yes |
One of the caller's own security events.
| Field | Type | Required | Notes |
|---|---|---|---|
action |
string | yes | The audit action, e.g. session.login, passkey.added
|
at |
string (date-time) | yes | |
details |
object | yes | A safe subset of the audit details |
id |
integer | yes | |
ip_prefix |
string or null | yes | The address of the request, shortened |
network |
"local" | "public" | "unknown"
|
yes | |
outcome |
string | yes |
success, failure or denied
|
target_type |
string or null | yes |
The top of the security page: password status, alert setting and counts.
| Field | Type | Required | Notes |
|---|---|---|---|
known_devices |
integer | yes | |
must_change_password |
boolean | yes | |
new_login_alerts |
boolean | yes | Notify on a login from a device not seen before (in-app and push) |
passkeys |
integer | yes | |
password_changed_at |
string (date-time) or null | yes | Last change; null when unknown (set before the security center existed) |
password_set |
boolean | yes | |
personal_tokens |
integer | yes | Active personal access tokens in this account |
providers |
array of string | yes | Linked login providers (github, apple) |
sessions |
integer | yes | Live login sessions in all accounts |
One of the caller's live login sessions (a browser or an app installation).
| Field | Type | Required | Notes |
|---|---|---|---|
account_id |
string (uuid) | yes | |
browser |
string or null | yes | Browser family from the user agent, no version |
client |
"browser" | "app" | "script" | "unknown"
|
yes | |
created_at |
string (date-time) | yes | When the session started (the login) |
current |
boolean | yes | The session of this request |
expires_at |
string (date-time) | yes | When the session ends unless it is used again |
id |
string (uuid) | yes | The login session (the sid of its access tokens) |
ip_prefix |
string or null | yes | The address shortened to its network (203.0.113.x, an IPv6 /48); MowDeck asks no location service |
label |
string | yes |
Firefox on Windows, MowDeck app on iOS (English) |
last_used_at |
string (date-time) | yes | The last refresh (about every 10 minutes) |
method |
string or null | yes | How it started: pwd, passkey, github, apple
|
network |
"local" | "public" | "unknown"
|
yes |
local: a private, loopback or link-local address (the home network) |
os |
string or null | yes | Operating system from the user agent |
POST /me/sessions/revoke-others.
| Field | Type | Required | Notes |
|---|---|---|---|
revoked |
integer | yes | How many sessions ended |
POST /me/step-up/passkey: the answer to a challenge of the options endpoint.
| Field | Type | Required | Notes |
|---|---|---|---|
ceremony_id |
string (uuid) | yes | |
credential |
object | yes | The PublicKeyCredential as JSON (PublicKeyCredential.toJSON(): id, rawId, type, response with base64url fields, clientExtensionResults) |
POST /me/step-up/password: the caller's current password.
| Field | Type | Required | Notes |
|---|---|---|---|
password |
string | yes | min length 1; max length 256 |
POST /users: a sub-user with username and password (no e-mail needed).
| Field | Type | Required | Notes |
|---|---|---|---|
assignments |
array of AssignmentIn | no | max items 50 |
display_name |
string or null | no | |
email |
string or null | no | |
must_change_password |
boolean | no | default false
|
password |
string | yes | min length 1; max length 256 |
username |
string | yes | min length 1; max length 64 |
POST /token: exchange an API token for an access token.
| Field | Type | Required | Notes |
|---|---|---|---|
grant_type |
"api_token" |
no | default "api_token"
|
token |
string | yes | min length 1; max length 200 |
Permission keys of an API token at one level.
| Field | Type | Required | Notes |
|---|---|---|---|
level |
LevelIn | yes | |
permissions |
array of string | yes | min items 1; max items 50 |
An access token (and for logins the refresh token, shown once).
| Field | Type | Required | Notes |
|---|---|---|---|
access_token |
string | yes | |
account_id |
string (uuid) or null | yes | |
auth_time |
string (date-time) or null | no | When the user last authenticated interactively (login or step-up); critical actions need this to be recent |
expires_at |
string (date-time) | yes | |
expires_in |
integer | yes | |
refresh_expires_at |
string (date-time) or null | no | |
refresh_token |
string or null | no | |
session_id |
string (uuid) or null | no | |
token_type |
"Bearer" |
no | default "Bearer"
|
Why an API token exists: who manages it and which rules it follows (ADR 0064).
Type: "integration" | "personal"
GET /ui-areas: one area of the web app shell and the module that announces it.
| Field | Type | Required | Notes |
|---|---|---|---|
labels |
map of string | no | |
menu_label |
string | yes | |
module |
string | yes | |
module_version |
string | yes | |
required_permission |
string | yes | |
route |
string | yes |
PATCH /users/{id}.
| Field | Type | Required | Notes |
|---|---|---|---|
display_name |
string | yes | min length 1; max length 200 |
| Field | Type | Required | Notes |
|---|---|---|---|
ctx |
object | no | |
input |
any | no | |
loc |
array of string or integer | yes | |
msg |
string | yes | |
type |
string | yes |
POST /me/widget-credentials.
| Field | Type | Required | Notes |
|---|---|---|---|
device_name |
string | yes | Shown in the account's token list as iOS widgets: <device_name>.; min length 1; max length 80 |
replaces |
string (uuid) or null | no | An earlier widget credential of the caller on this device: revoked in the same transaction (rotation). |
A widget credential: an API token for the iOS widgets (never with its secret, except once at creation).
| Field | Type | Required | Notes |
|---|---|---|---|
created_at |
string (date-time) | yes | |
expires_at |
string (date-time) or null | yes | |
id |
string (uuid) | yes | |
last_used_at |
string (date-time) or null | yes | |
name |
string | yes | |
permissions |
array of string | yes | |
revoked_at |
string (date-time) or null | yes | |
token |
string or null | no | The secret (mdk_...), returned only at creation. Exchange it at POST /token for 10 minute access tokens. |
Mirrored from docs/reference/api/identity.md at commit 92e148f2170c557620edba69704ad69dc99a9cba. Edit the file in the repository, not this wiki page.
Mirrored from the docs/ directory at commit 92e148f2170c557620edba69704ad69dc99a9cba. 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)