Files
home-automation/openapi/openapi.yaml
T

2387 lines
61 KiB
YAML

openapi: 3.1.0
info:
title: Home Automation Backend (Python)
description: Home automation backend with auth, runtime config, Home Assistant integrations,
TickTick integration, and SQLite-backed recorders.
version: 0.1.0
paths:
/status:
get:
tags:
- system
summary: Get Status
operationId: get_status_status_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/StatusResponse'
/api/config:
get:
tags:
- api-config
summary: Get Config
description: Return all configuration sections. Secret field values are masked
(empty string).
operationId: get_config_api_config_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ConfigResponse'
put:
tags:
- api-config
summary: Put Config
description: 'Save configuration updates.
- Blank secret value keeps the existing stored value (no change).
- Invalid values return 422 and nothing is written to the database.
- If MQTT-related settings changed, the MQTT client reconnects automatically.'
operationId: put_config_api_config_put
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ConfigUpdateRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ConfigUpdateResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/config/smtp/test:
post:
tags:
- api-config
summary: Post Smtp Test
description: 'Send a test SMTP email using the current runtime settings.
Returns a structured result indicating success or the category of failure.
Three possible outcomes:
- 200 { "result": "success", "message": ... }
- 400 { "result": "config-error", "message": ... } (EmailConfigurationError)
- 502 { "result": "failed", "message": ... } (EmailDeliveryError)
SMTP credentials are never echoed in the response.'
operationId: post_smtp_test_api_config_smtp_test_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SmtpTestResponse'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/SmtpTestResponse'
description: Bad Request
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/SmtpTestResponse'
description: Bad Gateway
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/config/mqtt/test:
post:
tags:
- api-config
summary: Post Mqtt Test
description: 'Test MQTT broker connectivity by attempting to connect and publishing
a
test message to ``<ha_discovery_prefix>/home-automation/test``.
The message is visible in MQTT Explorer (or any subscriber) so users can
confirm the full broker publish path is working.
Three possible outcomes:
- 200 { "result": "success", "message": ... }
- 400 { "result": "config-error", "message": ... } (not configured)
- 502 { "result": "failed", "message": ... } (connection/publish
error)
MQTT credentials are never echoed in the response.'
operationId: post_mqtt_test_api_config_mqtt_test_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/MqttTestResponse'
'400':
content:
application/json:
schema:
$ref: '#/components/schemas/MqttTestResponse'
description: Bad Request
'502':
content:
application/json:
schema:
$ref: '#/components/schemas/MqttTestResponse'
description: Bad Gateway
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/locations:
get:
tags:
- api-data
summary: Get Locations
description: 'Return location records with optional time-window filtering and
pagination.
- ``start`` / ``end`` are ISO8601 strings; filtering is **inclusive** on both
bounds.
- Results are ordered by ``datetime`` ascending.
- ``limit`` is capped at 5000 to prevent full-table exports.'
operationId: get_locations_api_locations_get
parameters:
- name: limit
in: query
required: false
schema:
type: integer
maximum: 5000
minimum: 1
default: 1000
title: Limit
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
title: Offset
- name: start
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: Start
- name: end
in: query
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: End
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/LocationsResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/poo:
get:
tags:
- api-data
summary: Get Poo
description: 'Return poo records ordered by timestamp descending (most recent
first).
``limit`` is capped at 1000 to prevent full-table exports.'
operationId: get_poo_api_poo_get
parameters:
- name: limit
in: query
required: false
schema:
type: integer
maximum: 1000
minimum: 1
default: 100
title: Limit
- name: offset
in: query
required: false
schema:
type: integer
minimum: 0
default: 0
title: Offset
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PooResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/public-ip:
get:
tags:
- api-data
summary: Get Public Ip
description: 'Return the current public IP state and recent history.
- ``state`` is ``null`` if no IP check has been performed yet.
- ``history`` is ordered by ``observed_at`` descending (most recent first).
- ``limit`` applies to the history list and is capped at 1000.'
operationId: get_public_ip_api_public_ip_get
parameters:
- name: limit
in: query
required: false
schema:
type: integer
maximum: 1000
minimum: 1
default: 100
title: Limit
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PublicIPResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/locations/{person}/{datetime}:
patch:
tags:
- api-data
summary: Patch Location
description: 'Update the non-PK fields of a single location record.
- ``person`` and ``datetime`` identify the row (composite PK) and are immutable.
- Only ``latitude``, ``longitude``, and ``altitude`` may be updated.
- Omitted body fields are left unchanged.
- Returns **404** if the PK does not exist.'
operationId: patch_location_api_locations__person___datetime__patch
parameters:
- name: person
in: path
required: true
schema:
type: string
title: Person
- name: datetime
in: path
required: true
schema:
type: string
title: Datetime
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/LocationUpdateRequest'
default: {}
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/LocationRecord'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
delete:
tags:
- api-data
summary: Delete Location Record
description: 'Delete the single location record identified by its composite
PK.
- Exactly one row is deleted; **404** if the PK does not exist.
- No batch delete / truncate path is available.'
operationId: delete_location_record_api_locations__person___datetime__delete
parameters:
- name: person
in: path
required: true
schema:
type: string
title: Person
- name: datetime
in: path
required: true
schema:
type: string
title: Datetime
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'204':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/poo/{timestamp}:
patch:
tags:
- api-data
summary: Patch Poo
description: 'Update the non-PK fields of a single poo record.
- ``timestamp`` is the PK and is immutable.
- Only ``status``, ``latitude``, and ``longitude`` may be updated.
- Omitted body fields are left unchanged.
- Returns **404** if the PK does not exist.'
operationId: patch_poo_api_poo__timestamp__patch
parameters:
- name: timestamp
in: path
required: true
schema:
type: string
title: Timestamp
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/PooUpdateRequest'
default: {}
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PooRecord'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
delete:
tags:
- api-data
summary: Delete Poo
description: 'Delete the single poo record identified by its PK.
- Exactly one row is deleted; **404** if the PK does not exist.
- No batch delete / truncate path is available.'
operationId: delete_poo_api_poo__timestamp__delete
parameters:
- name: timestamp
in: path
required: true
schema:
type: string
title: Timestamp
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'204':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/expose:
get:
tags:
- api-expose
summary: Get Expose
description: 'Return the full exposable-entity catalog with toggle states and
MQTT status.
The catalog is computed dynamically from registered providers (e.g. the
Modbus provider enumerates all enabled devices and their metric entities).
Toggle states come from the ``exposed_entity_toggle`` table; entities with
no row default to ``enabled=False``.'
operationId: get_expose_api_expose_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ExposeResponse'
put:
tags:
- api-expose
summary: Put Expose
description: 'Set per-entity toggle state.
Accepts a map of ``{key: bool}`` and upserts rows in the
``exposed_entity_toggle`` table. Only keys present in ``body.toggles``
are touched; other entities'' toggles are left unchanged.
After writing the toggles, triggers a HA Discovery re-publish so any
changes (enabled ↔ disabled) are reflected in Home Assistant immediately.'
operationId: put_expose_api_expose_put
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ExposeUpdateRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ExposeUpdateResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/expose/republish:
post:
tags:
- api-expose
summary: Post Expose Republish
description: 'Manually trigger a full HA Discovery re-publish.
Calls ``publish_discovery(session)`` from the HA discovery service (M5-T11).
Returns a status indicating whether the publish was attempted (or skipped
because MQTT / discovery is not enabled / connected).'
operationId: post_expose_republish_api_expose_republish_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/RepublishResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/modbus/profiles:
get:
tags:
- api-modbus
summary: Get Profiles
description: 'List all available Modbus YAML profiles (name + description).
Intended for the front-end''s device-creation profile drop-down.'
operationId: get_profiles_api_modbus_profiles_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusProfilesResponse'
/api/modbus/devices:
get:
tags:
- api-modbus
summary: List Devices
description: Return all Modbus devices (no pagination — device counts stay small).
operationId: list_devices_api_modbus_devices_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusDeviceListResponse'
post:
tags:
- api-modbus
summary: Create Device
description: 'Create a new Modbus device.
- Validates that the referenced ``profile`` exists; returns 422 if not.
- Returns 201 with the created device on success.'
operationId: create_device_api_modbus_devices_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusDeviceCreate'
responses:
'201':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusDeviceResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/modbus/devices/{uuid}:
get:
tags:
- api-modbus
summary: Get Device
description: Return a single Modbus device by UUID.
operationId: get_device_api_modbus_devices__uuid__get
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusDeviceResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
patch:
tags:
- api-modbus
summary: Patch Device
description: 'Partially update a Modbus device (including enable/disable).
Only fields explicitly provided in the request body are updated.
Providing ``profile`` triggers a profile-existence check (422 if unknown).'
operationId: patch_device_api_modbus_devices__uuid__patch
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusDeviceUpdate'
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusDeviceResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
delete:
tags:
- api-modbus
summary: Delete Device
description: 'Delete a Modbus device.
Returns 409 Conflict if the device has any associated readings; use
``enabled=false`` to disable it instead.
**Application-layer safety**: the check is performed via an explicit
SELECT COUNT query — not by relying on SQLite''s FK RESTRICT constraint,
which is not enforced at runtime in this project (no PRAGMA foreign_keys=ON).'
operationId: delete_device_api_modbus_devices__uuid__delete
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'204':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/modbus/devices/{uuid}/latest:
get:
tags:
- api-modbus
summary: Get Latest Reading
description: 'Return the most recent reading for a device.
If no readings exist yet, returns ``{"found": false, "recorded_at": null,
"payload": null}`` (200, not 404) so the front-end can distinguish
"device exists but has no data" from "device not found".'
operationId: get_latest_reading_api_modbus_devices__uuid__latest_get
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusLatestResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/modbus/devices/{uuid}/readings:
get:
tags:
- api-modbus
summary: Get Readings
description: 'Return time-range readings for a device.
When the window contains more rows than ``limit``, the **most recent** N rows
are returned (``ORDER BY recorded_at DESC LIMIT n``), then reversed to
ascending order before being sent to the client. This ensures that for long
time-range requests (e.g. 6 h / 24 h) the caller always sees the latest data
rather than the oldest segment of the window.
When the window has fewer rows than ``limit`` the full window is returned
in
ascending order — behaviour is identical to a plain ascending query.
The response schema is unchanged: items are always ``recorded_at`` ascending.
The query uses the ``(device_id, recorded_at)`` composite index for
efficient time-window scans.
Query parameters:
- ``start``: inclusive lower bound (ISO8601 datetime)
- ``end``: inclusive upper bound (ISO8601 datetime)
- ``limit``: max rows to return (default 500, max {_READINGS_LIMIT_MAX})'
operationId: get_readings_api_modbus_devices__uuid__readings_get
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
- name: start
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Start
- name: end
in: query
required: false
schema:
anyOf:
- type: string
format: date-time
- type: 'null'
title: End
- name: limit
in: query
required: false
schema:
type: integer
maximum: 5000
minimum: 1
default: 500
title: Limit
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusReadingsResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/modbus/devices/{uuid}/metrics:
get:
tags:
- api-modbus
summary: Get Metrics
description: 'Return the metric catalogue for a device''s profile.
Each entry has ``key``, ``label`` (derived from key if the profile has
none — underscores → spaces, title-cased), ``unit``, and ``device_class``.
This is the authoritative metadata source for front-end card labels and
chart axis labels.'
operationId: get_metrics_api_modbus_devices__uuid__metrics_get
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusMetricsResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/modbus/devices/{uuid}/test:
post:
tags:
- api-modbus
summary: Test Read
description: 'Immediately read and decode the device once without persisting
any data.
Useful for validating gateway connectivity and Modbus address settings
before relying on the background polling job.
This is a write-class endpoint (it initiates network I/O on demand) and
therefore requires a CSRF token. The response payload is never stored.'
operationId: test_read_api_modbus_devices__uuid__test_post
parameters:
- name: uuid
in: path
required: true
schema:
type: string
title: Uuid
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/ModbusTestReadResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/session:
get:
tags:
- api-session
summary: Get Session
description: Return the current session user and CSRF token. Returns 401 if
not authenticated.
operationId: get_session_api_session_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SessionResponse'
/api/auth/login:
post:
tags:
- api-session
summary: Post Login
description: 'Authenticate with username and password.
On success, sets an HttpOnly session cookie and returns the session user +
CSRF token.
On failure, returns 401 with no cookie set.
Repeated failures trigger exponential back-off (429 + Retry-After).
No X-CSRF-Token required (unauthenticated endpoint).'
operationId: post_login_api_auth_login_post
requestBody:
content:
application/json:
schema:
$ref: '#/components/schemas/LoginRequest'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/SessionResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/auth/logout:
post:
tags:
- api-session
summary: Post Logout
description: 'Revoke the current session and clear the session cookie.
Requires authentication and X-CSRF-Token header.
Returns 204 No Content.'
operationId: post_logout_api_auth_logout_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/auth/password:
post:
tags:
- api-session
summary: Post Change Password
description: 'Change the current user''s password.
Requires authentication and X-CSRF-Token header.
On AuthPasswordChangeError returns 400 with a generic message.
On success, force_password_change becomes False (handled by the service).
Returns 204 No Content.'
operationId: post_change_password_api_auth_password_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/PasswordChangeRequest'
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/auth/totp/setup:
post:
tags:
- api-session
summary: Post Totp Setup
description: 'Generate a new pending TOTP secret, otpauth URI, and one-time
recovery codes.
The secret is stored in the DB but TOTP is NOT yet enabled (totp_enabled stays
False until the user confirms with POST /api/auth/totp/enable).
Recovery codes are returned here as plaintext exactly once; their Argon2 hashes
are persisted immediately so enable only needs to flip the enabled flag.
Repeating this call replaces any prior pending secret and regenerates codes.
Requires: session cookie + X-CSRF-Token.'
operationId: post_totp_setup_api_auth_totp_setup_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/TotpSetupResponse'
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/auth/totp/enable:
post:
tags:
- api-session
summary: Post Totp Enable
description: 'Enable TOTP by confirming with the current 6-digit code from the
authenticator app.
Requires a prior call to POST /api/auth/totp/setup (so that a pending secret
exists). On success, totp_enabled becomes True.
Returns 400 if the code is wrong or there is no pending secret.
Requires: session cookie + X-CSRF-Token.'
operationId: post_totp_enable_api_auth_totp_enable_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TotpEnableRequest'
responses:
'204':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/auth/totp/disable:
post:
tags:
- api-session
summary: Post Totp Disable
description: 'Disable TOTP. The caller must provide exactly one of:
- ``password``: the user''s current login password, OR
- ``code``: the current 6-digit TOTP code.
On success: totp_enabled=False, totp_secret cleared, all recovery codes deleted.
Returns 400 if neither credential matches or neither is provided.
Requires: session cookie + X-CSRF-Token.'
operationId: post_totp_disable_api_auth_totp_disable_post
parameters:
- name: X-CSRF-Token
in: header
required: false
schema:
anyOf:
- type: string
- type: 'null'
title: X-Csrf-Token
requestBody:
required: true
content:
application/json:
schema:
$ref: '#/components/schemas/TotpDisableRequest'
responses:
'204':
description: Successful Response
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/api/auth/totp:
get:
tags:
- api-session
summary: Get Totp Status
description: 'Return the current TOTP status for the authenticated user.
Response contains only ``{"enabled": bool}``.
Secret and recovery codes are NEVER returned here.
Requires: session cookie only (no CSRF — read-only).'
operationId: get_totp_status_api_auth_totp_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/TotpStatusResponse'
/homeassistant/publish:
post:
tags:
- homeassistant
summary: Publish From Homeassistant
operationId: publish_from_homeassistant_homeassistant_publish_post
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
/location/record:
post:
tags:
- location
summary: Create Location Record
operationId: create_location_record_location_record_post
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
/poo/record:
post:
tags:
- poo
summary: Create Poo Record
operationId: create_poo_record_poo_record_post
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
/poo/latest:
get:
tags:
- poo
summary: Notify Latest Poo
operationId: notify_latest_poo_poo_latest_get
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
/public-ip/check:
get:
tags:
- public-ip
summary: Run Public Ip Check
operationId: run_public_ip_check_public_ip_check_get
responses:
'200':
description: Successful Response
content:
application/json:
schema:
$ref: '#/components/schemas/PublicIPCheckResponse'
/ticktick/auth/start:
get:
tags:
- ticktick
summary: Start Ticktick Auth
operationId: start_ticktick_auth_ticktick_auth_start_get
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
/ticktick/auth/code:
get:
tags:
- ticktick
summary: Handle Ticktick Auth Code
operationId: handle_ticktick_auth_code_ticktick_auth_code_get
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
components:
schemas:
CatalogEntrySchema:
properties:
entity:
$ref: '#/components/schemas/ExposableEntitySchema'
enabled:
type: boolean
title: Enabled
type: object
required:
- entity
- enabled
title: CatalogEntrySchema
description: An entity from the catalog with its current toggle state.
ConfigField:
properties:
env_name:
type: string
title: Env Name
label:
type: string
title: Label
value:
type: string
title: Value
secret:
type: boolean
title: Secret
input_type:
type: string
title: Input Type
configured:
type: boolean
title: Configured
type: object
required:
- env_name
- label
- value
- secret
- input_type
- configured
title: ConfigField
ConfigResponse:
properties:
sections:
items:
$ref: '#/components/schemas/ConfigSection'
type: array
title: Sections
type: object
required:
- sections
title: ConfigResponse
ConfigSection:
properties:
name:
type: string
title: Name
fields:
items:
$ref: '#/components/schemas/ConfigField'
type: array
title: Fields
type: object
required:
- name
- fields
title: ConfigSection
ConfigUpdateRequest:
properties:
updates:
additionalProperties:
type: string
type: object
title: Updates
type: object
required:
- updates
title: ConfigUpdateRequest
description: Flat mapping of env_name → value, mirroring the existing form semantics.
ConfigUpdateResponse:
properties:
sections:
items:
$ref: '#/components/schemas/ConfigSection'
type: array
title: Sections
type: object
required:
- sections
title: ConfigUpdateResponse
DeviceInfoSchema:
properties:
identifiers:
items:
type: string
type: array
title: Identifiers
name:
type: string
title: Name
type: object
required:
- identifiers
- name
title: DeviceInfoSchema
description: HA device grouping info for an exposable entity.
ExposableEntitySchema:
properties:
key:
type: string
title: Key
component:
type: string
title: Component
device:
$ref: '#/components/schemas/DeviceInfoSchema'
device_class:
anyOf:
- type: string
- type: 'null'
title: Device Class
unit:
type: string
title: Unit
name:
type: string
title: Name
state_class:
anyOf:
- type: string
- type: 'null'
title: State Class
type: object
required:
- key
- component
- device
- device_class
- unit
- name
title: ExposableEntitySchema
description: 'One exposable entity in the catalog.
``value_getter`` is intentionally excluded — it is a non-serialisable
callable and is only used internally by the HA Discovery service.'
ExposeResponse:
properties:
catalog:
items:
$ref: '#/components/schemas/CatalogEntrySchema'
type: array
title: Catalog
mqtt_status:
$ref: '#/components/schemas/MqttStatusSchema'
type: object
required:
- catalog
- mqtt_status
title: ExposeResponse
description: Response for GET /api/expose.
ExposeUpdateRequest:
properties:
toggles:
additionalProperties:
type: boolean
type: object
title: Toggles
type: object
required:
- toggles
title: ExposeUpdateRequest
description: 'Request body for PUT /api/expose.
``toggles`` is a map from entity key to desired enabled state (bool).
Only keys present in the map are updated; absent keys are untouched.'
ExposeUpdateResponse:
properties:
catalog:
items:
$ref: '#/components/schemas/CatalogEntrySchema'
type: array
title: Catalog
mqtt_status:
$ref: '#/components/schemas/MqttStatusSchema'
type: object
required:
- catalog
- mqtt_status
title: ExposeUpdateResponse
description: Response for PUT /api/expose (returns updated catalog + status).
HTTPValidationError:
properties:
detail:
items:
$ref: '#/components/schemas/ValidationError'
type: array
title: Detail
type: object
title: HTTPValidationError
LocationRecord:
properties:
person:
type: string
title: Person
datetime:
type: string
title: Datetime
latitude:
type: number
title: Latitude
longitude:
type: number
title: Longitude
altitude:
anyOf:
- type: number
- type: 'null'
title: Altitude
type: object
required:
- person
- datetime
- latitude
- longitude
- altitude
title: LocationRecord
LocationUpdateRequest:
properties:
latitude:
anyOf:
- type: number
- type: 'null'
title: Latitude
longitude:
anyOf:
- type: number
- type: 'null'
title: Longitude
altitude:
anyOf:
- type: number
- type: 'null'
title: Altitude
type: object
title: LocationUpdateRequest
description: PATCH body for a location record — all fields optional; PK fields
excluded.
LocationsResponse:
properties:
items:
items:
$ref: '#/components/schemas/LocationRecord'
type: array
title: Items
limit:
type: integer
title: Limit
offset:
type: integer
title: Offset
type: object
required:
- items
- limit
- offset
title: LocationsResponse
LoginRequest:
properties:
username:
type: string
title: Username
password:
type: string
title: Password
totp_code:
anyOf:
- type: string
- type: 'null'
title: Totp Code
type: object
required:
- username
- password
title: LoginRequest
MetricInfo:
properties:
key:
type: string
title: Key
label:
type: string
title: Label
unit:
type: string
title: Unit
device_class:
type: string
title: Device Class
type: object
required:
- key
- label
- unit
- device_class
title: MetricInfo
description: Metadata for a single measurable quantity in a device's profile.
ModbusDeviceCreate:
properties:
friendly_name:
type: string
maxLength: 255
minLength: 1
title: Friendly Name
transport:
type: string
maxLength: 16
title: Transport
default: tcp
host:
type: string
maxLength: 255
minLength: 1
title: Host
port:
type: integer
maximum: 65535.0
minimum: 1.0
title: Port
default: 502
unit_id:
type: integer
maximum: 247.0
minimum: 0.0
title: Unit Id
default: 1
profile:
type: string
maxLength: 64
minLength: 1
title: Profile
poll_interval_s:
type: integer
maximum: 3600.0
minimum: 1.0
title: Poll Interval S
default: 5
enabled:
type: boolean
title: Enabled
default: true
type: object
required:
- friendly_name
- host
- profile
title: ModbusDeviceCreate
description: Request body for POST /api/modbus/devices.
ModbusDeviceListResponse:
properties:
items:
items:
$ref: '#/components/schemas/ModbusDeviceResponse'
type: array
title: Items
total:
type: integer
title: Total
type: object
required:
- items
- total
title: ModbusDeviceListResponse
description: Response schema for listing Modbus devices.
ModbusDeviceResponse:
properties:
uuid:
type: string
title: Uuid
friendly_name:
type: string
title: Friendly Name
transport:
type: string
title: Transport
host:
type: string
title: Host
port:
type: integer
title: Port
unit_id:
type: integer
title: Unit Id
profile:
type: string
title: Profile
poll_interval_s:
type: integer
title: Poll Interval S
enabled:
type: boolean
title: Enabled
last_poll_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Last Poll At
last_poll_ok:
anyOf:
- type: boolean
- type: 'null'
title: Last Poll Ok
created_at:
type: string
format: date-time
title: Created At
updated_at:
type: string
format: date-time
title: Updated At
type: object
required:
- uuid
- friendly_name
- transport
- host
- port
- unit_id
- profile
- poll_interval_s
- enabled
- last_poll_at
- last_poll_ok
- created_at
- updated_at
title: ModbusDeviceResponse
description: Response schema for a single Modbus device.
ModbusDeviceUpdate:
properties:
friendly_name:
anyOf:
- type: string
maxLength: 255
minLength: 1
- type: 'null'
title: Friendly Name
transport:
anyOf:
- type: string
maxLength: 16
- type: 'null'
title: Transport
host:
anyOf:
- type: string
maxLength: 255
minLength: 1
- type: 'null'
title: Host
port:
anyOf:
- type: integer
maximum: 65535.0
minimum: 1.0
- type: 'null'
title: Port
unit_id:
anyOf:
- type: integer
maximum: 247.0
minimum: 0.0
- type: 'null'
title: Unit Id
profile:
anyOf:
- type: string
maxLength: 64
minLength: 1
- type: 'null'
title: Profile
poll_interval_s:
anyOf:
- type: integer
maximum: 3600.0
minimum: 1.0
- type: 'null'
title: Poll Interval S
enabled:
anyOf:
- type: boolean
- type: 'null'
title: Enabled
type: object
title: ModbusDeviceUpdate
description: Request body for PATCH /api/modbus/devices/{uuid} — all fields
optional.
ModbusLatestResponse:
properties:
found:
type: boolean
title: Found
recorded_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Recorded At
payload:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Payload
type: object
required:
- found
- recorded_at
- payload
title: ModbusLatestResponse
description: 'Response for the /latest endpoint.
``found`` is False and ``recorded_at``/``payload`` are None when the device
has no readings yet. Callers should check ``found`` before using the values.'
ModbusMetricsResponse:
properties:
profile:
type: string
title: Profile
metrics:
items:
$ref: '#/components/schemas/MetricInfo'
type: array
title: Metrics
type: object
required:
- profile
- metrics
title: ModbusMetricsResponse
description: Response schema for GET /api/modbus/devices/{uuid}/metrics.
ModbusProfilesResponse:
properties:
profiles:
items:
$ref: '#/components/schemas/ProfileSummary'
type: array
title: Profiles
type: object
required:
- profiles
title: ModbusProfilesResponse
description: Response schema for GET /api/modbus/profiles.
ModbusReadingResponse:
properties:
recorded_at:
type: string
format: date-time
title: Recorded At
payload:
additionalProperties: true
type: object
title: Payload
type: object
required:
- recorded_at
- payload
title: ModbusReadingResponse
description: 'A single reading row: timestamp + decoded payload.'
ModbusReadingsResponse:
properties:
items:
items:
$ref: '#/components/schemas/ModbusReadingResponse'
type: array
title: Items
type: object
required:
- items
title: ModbusReadingsResponse
description: Response schema for the readings time-range endpoint.
ModbusTestReadResponse:
properties:
ok:
type: boolean
title: Ok
payload:
anyOf:
- additionalProperties: true
type: object
- type: 'null'
title: Payload
error:
anyOf:
- type: string
- type: 'null'
title: Error
type: object
required:
- ok
title: ModbusTestReadResponse
description: 'Response for POST /api/modbus/devices/{uuid}/test.
On success ``ok=True`` and ``payload`` contains the decoded values.
On failure ``ok=False`` and ``error`` describes the problem.'
MqttStatusSchema:
properties:
mqtt_configured:
type: boolean
title: Mqtt Configured
mqtt_connected:
type: boolean
title: Mqtt Connected
discovery_enabled:
type: boolean
title: Discovery Enabled
type: object
required:
- mqtt_configured
- mqtt_connected
- discovery_enabled
title: MqttStatusSchema
description: Connection status for MQTT and HA Discovery.
MqttTestResponse:
properties:
result:
type: string
enum:
- success
- config-error
- failed
title: Result
message:
type: string
title: Message
type: object
required:
- result
- message
title: MqttTestResponse
description: Response from POST /api/config/mqtt/test.
PasswordChangeRequest:
properties:
current_password:
type: string
title: Current Password
new_password:
type: string
title: New Password
confirm_password:
type: string
title: Confirm Password
type: object
required:
- current_password
- new_password
- confirm_password
title: PasswordChangeRequest
PooRecord:
properties:
timestamp:
type: string
title: Timestamp
status:
type: string
title: Status
latitude:
type: number
title: Latitude
longitude:
type: number
title: Longitude
type: object
required:
- timestamp
- status
- latitude
- longitude
title: PooRecord
PooResponse:
properties:
items:
items:
$ref: '#/components/schemas/PooRecord'
type: array
title: Items
limit:
type: integer
title: Limit
offset:
type: integer
title: Offset
type: object
required:
- items
- limit
- offset
title: PooResponse
PooUpdateRequest:
properties:
status:
anyOf:
- type: string
- type: 'null'
title: Status
latitude:
anyOf:
- type: number
- type: 'null'
title: Latitude
longitude:
anyOf:
- type: number
- type: 'null'
title: Longitude
type: object
title: PooUpdateRequest
description: PATCH body for a poo record — all fields optional; PK field excluded.
ProfileSummary:
properties:
name:
type: string
title: Name
description:
type: string
title: Description
type: object
required:
- name
- description
title: ProfileSummary
description: One entry in the GET /api/modbus/profiles response.
PublicIPCheckResponse:
properties:
status:
type: string
enum:
- first_seen
- unchanged
- changed
- error
title: Status
checked_at:
type: string
format: date-time
title: Checked At
changed:
type: boolean
title: Changed
type: object
required:
- status
- checked_at
- changed
title: PublicIPCheckResponse
PublicIPHistorySchema:
properties:
id:
type: integer
title: Id
ipv4:
type: string
title: Ipv4
observed_at:
type: string
format: date-time
title: Observed At
change_type:
type: string
title: Change Type
provider:
anyOf:
- type: string
- type: 'null'
title: Provider
type: object
required:
- id
- ipv4
- observed_at
- change_type
- provider
title: PublicIPHistorySchema
PublicIPResponse:
properties:
state:
anyOf:
- $ref: '#/components/schemas/PublicIPStateSchema'
- type: 'null'
history:
items:
$ref: '#/components/schemas/PublicIPHistorySchema'
type: array
title: History
type: object
required:
- state
- history
title: PublicIPResponse
PublicIPStateSchema:
properties:
id:
type: integer
title: Id
current_ipv4:
type: string
title: Current Ipv4
previous_ipv4:
anyOf:
- type: string
- type: 'null'
title: Previous Ipv4
first_seen_at:
type: string
format: date-time
title: First Seen At
last_checked_at:
type: string
format: date-time
title: Last Checked At
last_changed_at:
anyOf:
- type: string
format: date-time
- type: 'null'
title: Last Changed At
last_check_status:
type: string
title: Last Check Status
last_check_error:
anyOf:
- type: string
- type: 'null'
title: Last Check Error
last_provider:
anyOf:
- type: string
- type: 'null'
title: Last Provider
type: object
required:
- id
- current_ipv4
- previous_ipv4
- first_seen_at
- last_checked_at
- last_changed_at
- last_check_status
- last_check_error
- last_provider
title: PublicIPStateSchema
RepublishResponse:
properties:
ok:
type: boolean
title: Ok
message:
type: string
title: Message
type: object
required:
- ok
- message
title: RepublishResponse
description: Response for POST /api/expose/republish.
SessionResponse:
properties:
user:
$ref: '#/components/schemas/SessionUser'
csrf_token:
type: string
title: Csrf Token
type: object
required:
- user
- csrf_token
title: SessionResponse
SessionUser:
properties:
username:
type: string
title: Username
force_password_change:
type: boolean
title: Force Password Change
type: object
required:
- username
- force_password_change
title: SessionUser
SmtpTestResponse:
properties:
result:
type: string
enum:
- success
- config-error
- failed
title: Result
message:
type: string
title: Message
type: object
required:
- result
- message
title: SmtpTestResponse
description: Response from POST /api/config/smtp/test.
StatusResponse:
properties:
status:
type: string
title: Status
type: object
required:
- status
title: StatusResponse
TotpDisableRequest:
properties:
password:
anyOf:
- type: string
- type: 'null'
title: Password
code:
anyOf:
- type: string
- type: 'null'
title: Code
type: object
title: TotpDisableRequest
description: 'Disable TOTP by proving identity.
Exactly one of ``password`` or ``code`` must be provided.'
TotpEnableRequest:
properties:
code:
type: string
title: Code
type: object
required:
- code
title: TotpEnableRequest
description: The user confirms setup by providing the 6-digit TOTP code.
TotpSetupResponse:
properties:
secret:
type: string
title: Secret
otpauth_uri:
type: string
title: Otpauth Uri
recovery_codes:
items:
type: string
type: array
title: Recovery Codes
type: object
required:
- secret
- otpauth_uri
- recovery_codes
title: TotpSetupResponse
description: 'Returned once after a setup call.
``secret`` and ``recovery_codes`` are **one-time plaintext values**.
They are never returned again by any subsequent API call.
The frontend must display and instruct the user to save them before confirming.'
TotpStatusResponse:
properties:
enabled:
type: boolean
title: Enabled
type: object
required:
- enabled
title: TotpStatusResponse
description: Minimal status response — never exposes secret or recovery codes.
ValidationError:
properties:
loc:
items:
anyOf:
- type: string
- type: integer
type: array
title: Location
msg:
type: string
title: Message
type:
type: string
title: Error Type
type: object
required:
- loc
- msg
- type
title: ValidationError