Files
home-automation/openapi/openapi.yaml
T
tliu93 0fba7cfe11 M2-T03: add read-only data JSON API
- GET /api/locations (inclusive time window start/end, pagination, cap 5000)
- GET /api/poo (pagination, cap 1000, newest first)
- GET /api/public-ip (current state + recent history, cap 1000)
- all session-protected, read-only, bounded (no full-table export)
- typed response schemas; register router; regenerate openapi/
- tests/test_api_data.py
2026-06-12 23:24:17 +02:00

1001 lines
24 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'
/login:
get:
tags:
- auth
summary: Login Page
operationId: login_page_login_get
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
post:
tags:
- auth
summary: Login Submit
operationId: login_submit_login_post
requestBody:
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Body_login_submit_login_post'
required: true
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/config/change-password:
post:
tags:
- auth
summary: Change Password Submit
operationId: change_password_submit_config_change_password_post
requestBody:
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Body_change_password_submit_config_change_password_post'
required: true
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/logout:
post:
tags:
- auth
summary: Logout
operationId: logout_logout_post
requestBody:
content:
application/x-www-form-urlencoded:
schema:
$ref: '#/components/schemas/Body_logout_logout_post'
required: true
responses:
'200':
description: Successful Response
content:
application/json:
schema: {}
'422':
description: Validation Error
content:
application/json:
schema:
$ref: '#/components/schemas/HTTPValidationError'
/:
get:
tags:
- pages
summary: Home
operationId: home__get
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
/admin:
get:
tags:
- pages
summary: Admin Redirect
operationId: admin_redirect_admin_get
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
/config:
get:
tags:
- pages
summary: Config Page
operationId: config_page_config_get
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
post:
tags:
- pages
summary: Config Submit
operationId: config_submit_config_post
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
/config/smtp/test:
post:
tags:
- pages
summary: Smtp Test Submit
operationId: smtp_test_submit_config_smtp_test_post
responses:
'200':
description: Successful Response
content:
text/html:
schema:
type: string
/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.'
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/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/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.
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'
/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:
Body_change_password_submit_config_change_password_post:
properties:
current_password:
type: string
title: Current Password
new_password:
type: string
title: New Password
confirm_password:
type: string
title: Confirm Password
csrf_token:
type: string
title: Csrf Token
type: object
required:
- current_password
- new_password
- confirm_password
- csrf_token
title: Body_change_password_submit_config_change_password_post
Body_login_submit_login_post:
properties:
username:
type: string
title: Username
password:
type: string
title: Password
csrf_token:
type: string
title: Csrf Token
type: object
required:
- username
- password
- csrf_token
title: Body_login_submit_login_post
Body_logout_logout_post:
properties:
csrf_token:
type: string
title: Csrf Token
type: object
required:
- csrf_token
title: Body_logout_logout_post
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
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
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
type: object
required:
- username
- password
title: LoginRequest
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
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
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
StatusResponse:
properties:
status:
type: string
title: Status
type: object
required:
- status
title: StatusResponse
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