mirror of
https://github.com/pyMC-dev/pyMC_Repeater.git
synced 2026-06-11 08:44:46 +02:00
4149 lines
119 KiB
YAML
4149 lines
119 KiB
YAML
openapi: 3.0.0
|
|
info:
|
|
title: pyMC Repeater API
|
|
description: |
|
|
REST API for pyMC Repeater - LoRa mesh network repeater with room server functionality.
|
|
|
|
## Features
|
|
- System statistics and monitoring
|
|
- Packet history and analysis
|
|
- Identity management
|
|
- Access Control Lists (ACL)
|
|
- Room server messaging
|
|
- CAD calibration
|
|
- Noise floor monitoring
|
|
version: 1.0.0
|
|
contact:
|
|
name: pyMC Repeater
|
|
url: https://github.com/rightup/pyMC_Repeater
|
|
|
|
servers:
|
|
- url: /api
|
|
description: Current server (relative URLs with /api prefix)
|
|
- url: /
|
|
description: Current server root (for /auth endpoints)
|
|
- url: http://localhost:8080/api
|
|
description: Local development server
|
|
- url: http://{host}:8080/api
|
|
description: Custom host
|
|
variables:
|
|
host:
|
|
default: localhost
|
|
description: Repeater IP address or hostname
|
|
|
|
tags:
|
|
- name: Authentication
|
|
description: User authentication and API token management
|
|
- name: System
|
|
description: System statistics and control
|
|
- name: GPS
|
|
description: Local GPS receiver diagnostics
|
|
- name: Packets
|
|
description: Packet history and statistics
|
|
- name: Charts
|
|
description: Graph data and RRD metrics
|
|
- name: Noise Floor
|
|
description: Noise floor monitoring
|
|
- name: CAD Calibration
|
|
description: Channel Activity Detection calibration
|
|
- name: Adverts
|
|
description: Advertisement and contact management
|
|
- name: Transport Keys
|
|
description: Transport encryption key management
|
|
- name: Network Policy
|
|
description: Network flood policy and neighbor management
|
|
- name: Identities
|
|
description: Identity management
|
|
- name: ACL
|
|
description: Access Control Lists
|
|
- name: Room Server
|
|
description: Room server messaging
|
|
|
|
paths:
|
|
# ============================================================================
|
|
# Authentication Endpoints
|
|
# ============================================================================
|
|
/auth/login:
|
|
post:
|
|
tags: [Authentication]
|
|
summary: User login
|
|
description: Authenticate with username/password and receive JWT token
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [username, password, client_id]
|
|
properties:
|
|
username:
|
|
type: string
|
|
example: admin
|
|
password:
|
|
type: string
|
|
format: password
|
|
example: admin123
|
|
client_id:
|
|
type: string
|
|
description: Unique client identifier
|
|
example: web-client-abc123
|
|
responses:
|
|
'200':
|
|
description: Login successful
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
token:
|
|
type: string
|
|
description: JWT token
|
|
expires_in:
|
|
type: integer
|
|
description: Token expiry in seconds
|
|
username:
|
|
type: string
|
|
'401':
|
|
description: Invalid credentials
|
|
|
|
/auth/refresh:
|
|
post:
|
|
tags: [Authentication]
|
|
summary: Refresh JWT token
|
|
description: Extend session by refreshing JWT token
|
|
security:
|
|
- BearerAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [client_id]
|
|
properties:
|
|
client_id:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Token refreshed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
token:
|
|
type: string
|
|
expires_in:
|
|
type: integer
|
|
username:
|
|
type: string
|
|
|
|
/auth/verify:
|
|
get:
|
|
tags: [Authentication]
|
|
summary: Verify authentication
|
|
description: Check if current authentication is valid
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: Authentication valid
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
authenticated:
|
|
type: boolean
|
|
user:
|
|
type: object
|
|
|
|
/auth/change_password:
|
|
post:
|
|
tags: [Authentication]
|
|
summary: Change admin password
|
|
description: Change the admin password (requires authentication)
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [current_password, new_password]
|
|
properties:
|
|
current_password:
|
|
type: string
|
|
format: password
|
|
new_password:
|
|
type: string
|
|
format: password
|
|
minLength: 8
|
|
responses:
|
|
'200':
|
|
description: Password changed successfully
|
|
'401':
|
|
description: Current password incorrect
|
|
'400':
|
|
description: Invalid password format
|
|
|
|
/auth/tokens:
|
|
get:
|
|
tags: [Authentication]
|
|
summary: List API tokens
|
|
description: Get list of all API tokens (RESTful endpoint)
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: List of tokens
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
tokens:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
created_at:
|
|
type: string
|
|
format: date-time
|
|
last_used:
|
|
type: string
|
|
format: date-time
|
|
post:
|
|
tags: [Authentication]
|
|
summary: Create API token
|
|
description: Generate a new API token (RESTful endpoint)
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: Friendly name for the token
|
|
example: "My API Token"
|
|
responses:
|
|
'200':
|
|
description: Token created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
token:
|
|
type: string
|
|
description: The plaintext token (only shown once)
|
|
token_id:
|
|
type: integer
|
|
name:
|
|
type: string
|
|
warning:
|
|
type: string
|
|
|
|
/auth/tokens/{token_id}:
|
|
delete:
|
|
tags: [Authentication]
|
|
summary: Revoke API token
|
|
description: Delete/revoke an API token by ID (RESTful endpoint)
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: token_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Token revoked
|
|
'404':
|
|
description: Token not found
|
|
|
|
# ============================================================================
|
|
# System Endpoints
|
|
# ============================================================================
|
|
/stats:
|
|
get:
|
|
tags: [System]
|
|
summary: Get system statistics
|
|
description: Returns repeater uptime, packet counts, and version information
|
|
responses:
|
|
'200':
|
|
description: Successful response
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
uptime_secs:
|
|
type: integer
|
|
example: 3600
|
|
packets_received:
|
|
type: integer
|
|
example: 150
|
|
packets_sent:
|
|
type: integer
|
|
example: 120
|
|
version:
|
|
type: string
|
|
example: "1.0.0"
|
|
core_version:
|
|
type: string
|
|
example: "0.5.0"
|
|
|
|
/gps:
|
|
get:
|
|
tags: [GPS]
|
|
summary: Get local GPS diagnostics
|
|
description: Returns parsed NMEA fix, position, motion, accuracy, satellites, and raw sentence health.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: GPS diagnostics snapshot
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
running:
|
|
type: boolean
|
|
status:
|
|
type: object
|
|
fix:
|
|
type: object
|
|
position:
|
|
type: object
|
|
description: Effective receiver position for API clients
|
|
gps_position:
|
|
type: object
|
|
description: Raw position reported by the GPS receiver, even before a valid fix
|
|
manual_position:
|
|
type: object
|
|
nullable: true
|
|
description: Configured repeater latitude/longitude, when set to a non-zero coordinate
|
|
position_meta:
|
|
type: object
|
|
properties:
|
|
source:
|
|
type: string
|
|
enum: [gps, manual_config]
|
|
source_label:
|
|
type: string
|
|
policy:
|
|
type: string
|
|
enum: [manual_until_gps_fix, gps_only]
|
|
manual_config_available:
|
|
type: boolean
|
|
gps_fix_valid:
|
|
type: boolean
|
|
motion:
|
|
type: object
|
|
accuracy:
|
|
type: object
|
|
time:
|
|
type: object
|
|
time_sync:
|
|
type: object
|
|
description: GPS-to-system-clock sync status
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
state:
|
|
type: string
|
|
enum: [disabled, waiting_for_fix, waiting_for_time, ready, in_sync, synced, error, ignored]
|
|
last_attempt:
|
|
type: string
|
|
nullable: true
|
|
last_success:
|
|
type: string
|
|
nullable: true
|
|
last_error:
|
|
type: string
|
|
nullable: true
|
|
last_gps_time:
|
|
type: string
|
|
nullable: true
|
|
last_offset_seconds:
|
|
type: number
|
|
nullable: true
|
|
location_update:
|
|
type: object
|
|
description: GPS-fix-to-repeater-location update status
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
state:
|
|
type: string
|
|
enum: [disabled, unconfigured, waiting_for_fix, waiting_for_position, ready, updated, skipped, error]
|
|
last_attempt:
|
|
type: string
|
|
nullable: true
|
|
last_success:
|
|
type: string
|
|
nullable: true
|
|
last_error:
|
|
type: string
|
|
nullable: true
|
|
last_latitude:
|
|
type: number
|
|
nullable: true
|
|
last_longitude:
|
|
type: number
|
|
nullable: true
|
|
satellites:
|
|
type: object
|
|
nmea:
|
|
type: object
|
|
raw_attributes:
|
|
type: object
|
|
additionalProperties: true
|
|
|
|
/gps_stream:
|
|
get:
|
|
tags: [GPS]
|
|
summary: GPS diagnostics SSE stream
|
|
description: Server-Sent Events stream of live GPS diagnostics snapshots.
|
|
responses:
|
|
'200':
|
|
description: SSE stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
|
|
/send_advert:
|
|
post:
|
|
tags: [System]
|
|
summary: Send repeater advertisement
|
|
description: Manually trigger sending a repeater advertisement packet
|
|
responses:
|
|
'200':
|
|
description: Advertisement sent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
'405':
|
|
description: Method not allowed
|
|
|
|
/logs:
|
|
get:
|
|
tags: [System]
|
|
summary: Get system logs
|
|
description: Retrieve recent system logs
|
|
responses:
|
|
'200':
|
|
description: Log entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [logs]
|
|
properties:
|
|
logs:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required: [message, timestamp, level]
|
|
properties:
|
|
message:
|
|
type: string
|
|
timestamp:
|
|
type: string
|
|
format: date-time
|
|
level:
|
|
type: string
|
|
error:
|
|
type: string
|
|
|
|
/logs_stream:
|
|
get:
|
|
tags: [System]
|
|
summary: Stream system logs
|
|
description: Server-Sent Events stream of live system log entries.
|
|
parameters:
|
|
- name: since_id
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: integer
|
|
description: Resume the stream after this log entry id.
|
|
responses:
|
|
'200':
|
|
description: SSE stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
|
|
/hardware_stats:
|
|
get:
|
|
tags: [System]
|
|
summary: Get hardware statistics
|
|
description: CPU, memory, disk usage statistics
|
|
responses:
|
|
'200':
|
|
description: Hardware stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
cpu_percent:
|
|
type: number
|
|
memory_percent:
|
|
type: number
|
|
disk_usage:
|
|
type: object
|
|
|
|
/hardware_processes:
|
|
get:
|
|
tags: [System]
|
|
summary: Get process information
|
|
description: List running processes and their resource usage
|
|
responses:
|
|
'200':
|
|
description: Process list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: array
|
|
items:
|
|
type: object
|
|
|
|
/restart_service:
|
|
post:
|
|
tags: [System]
|
|
summary: Restart repeater service
|
|
description: Restart the repeater daemon service
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: Service restart initiated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/validate_config:
|
|
get:
|
|
tags: [System]
|
|
summary: Validate config.yaml before restart
|
|
description: Checks config syntax and required settings for the selected radio type.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: Validation completed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
valid:
|
|
type: boolean
|
|
blocked_restart:
|
|
type: boolean
|
|
errors:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
message:
|
|
type: string
|
|
warnings:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
path:
|
|
type: string
|
|
message:
|
|
type: string
|
|
summary:
|
|
type: object
|
|
properties:
|
|
error_count:
|
|
type: integer
|
|
warning_count:
|
|
type: integer
|
|
config_path:
|
|
type: string
|
|
message:
|
|
type: string
|
|
|
|
/openapi:
|
|
get:
|
|
tags: [System]
|
|
summary: Get OpenAPI specification
|
|
description: Returns the OpenAPI/Swagger specification for this API
|
|
responses:
|
|
'200':
|
|
description: OpenAPI spec
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/set_mode:
|
|
post:
|
|
tags: [System]
|
|
summary: Set repeater mode
|
|
description: |
|
|
Set TX mode. forward = repeat on; monitor = no repeat but companions/tenants can send;
|
|
no_tx = all transmission disabled (receive-only).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [mode]
|
|
properties:
|
|
mode:
|
|
type: string
|
|
enum: [forward, monitor, no_tx]
|
|
description: |
|
|
- forward: Repeat received packets; allow all local TX (default)
|
|
- monitor: Do not repeat; allow local TX (companions, adverts, etc.)
|
|
- no_tx: Do not repeat; no local TX (receive-only)
|
|
example: forward
|
|
examples:
|
|
forward:
|
|
value:
|
|
mode: forward
|
|
monitor:
|
|
value:
|
|
mode: monitor
|
|
no_tx:
|
|
value:
|
|
mode: no_tx
|
|
responses:
|
|
'200':
|
|
description: Mode changed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
examples:
|
|
success:
|
|
value:
|
|
success: true
|
|
data: "Mode set to forward"
|
|
'400':
|
|
description: Invalid mode
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/packet_stats:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get packet statistics
|
|
description: Returns packet counts, types, and routing statistics
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
minimum: 1
|
|
maximum: 168
|
|
description: Time range in hours (1-168 = 1 hour to 1 week)
|
|
example: 24
|
|
responses:
|
|
'200':
|
|
description: Packet statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
total_packets:
|
|
type: integer
|
|
received:
|
|
type: integer
|
|
transmitted:
|
|
type: integer
|
|
dropped:
|
|
type: integer
|
|
by_type:
|
|
type: object
|
|
by_route:
|
|
type: object
|
|
|
|
/set_duty_cycle:
|
|
post:
|
|
tags: [System]
|
|
summary: Set duty cycle
|
|
description: Enable or disable duty cycle limiting
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [enabled]
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
description: Enable duty cycle limiting
|
|
example: true
|
|
examples:
|
|
enable:
|
|
value:
|
|
enabled: true
|
|
disable:
|
|
value:
|
|
enabled: false
|
|
responses:
|
|
'200':
|
|
description: Duty cycle setting updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/update_duty_cycle_config:
|
|
post:
|
|
tags: [System]
|
|
summary: Update duty cycle configuration
|
|
description: Update detailed duty cycle timing configuration
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
enabled:
|
|
type: boolean
|
|
on_time:
|
|
type: integer
|
|
description: ON time in seconds
|
|
off_time:
|
|
type: integer
|
|
description: OFF time in seconds
|
|
example:
|
|
enabled: true
|
|
on_time: 300
|
|
off_time: 60
|
|
responses:
|
|
'200':
|
|
description: Duty cycle config updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/update_radio_config:
|
|
post:
|
|
tags: [System]
|
|
summary: Update radio configuration
|
|
description: Update LoRa radio parameters
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Radio config updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
# ============================================================================
|
|
# Packet Endpoints
|
|
# ============================================================================
|
|
/recent_packets:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get recent packets
|
|
description: Retrieve recent packet history
|
|
parameters:
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 100
|
|
minimum: 1
|
|
maximum: 1000
|
|
description: Maximum number of packets to return
|
|
responses:
|
|
'200':
|
|
description: Recent packets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: array
|
|
items:
|
|
type: object
|
|
|
|
/packet_by_hash:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get packet by hash
|
|
parameters:
|
|
- name: packet_hash
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Packet hash to lookup
|
|
responses:
|
|
'200':
|
|
description: Packet details
|
|
|
|
/packet_type_stats:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get packet type statistics
|
|
description: Statistics broken down by packet type
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
responses:
|
|
'200':
|
|
description: Packet type stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/route_stats:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get route statistics
|
|
description: Statistics broken down by route type
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
responses:
|
|
'200':
|
|
description: Route stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/filtered_packets:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get filtered packets
|
|
description: Retrieve packets filtered by type, route, and timestamp
|
|
parameters:
|
|
- name: type
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 15
|
|
description: Packet type filter
|
|
- name: route
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 3
|
|
description: Route type filter
|
|
- name: start_timestamp
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
description: Start timestamp (Unix)
|
|
- name: end_timestamp
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
description: End timestamp (Unix)
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1000
|
|
description: Maximum results
|
|
responses:
|
|
'200':
|
|
description: Filtered packets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
# ============================================================================
|
|
# Charts & RRD Endpoints
|
|
# ============================================================================
|
|
/rrd_data:
|
|
get:
|
|
tags: [Charts]
|
|
summary: Get RRD time-series data
|
|
description: |
|
|
Retrieve Round-Robin Database metrics for graphing.
|
|
|
|
**Note:** This endpoint extracts parameters from the request internally.
|
|
Parameters are handled automatically by the backend.
|
|
responses:
|
|
'200':
|
|
description: RRD time-series data
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
start_time:
|
|
type: integer
|
|
end_time:
|
|
type: integer
|
|
step:
|
|
type: integer
|
|
timestamps:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
metrics:
|
|
type: object
|
|
|
|
/packet_type_graph_data:
|
|
get:
|
|
tags: [Charts]
|
|
summary: Get packet type distribution graph data
|
|
description: Returns bar chart data showing packet counts by type
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
- name: resolution
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [average, max, min]
|
|
default: average
|
|
- name: types
|
|
in: query
|
|
schema:
|
|
type: string
|
|
default: all
|
|
description: Comma-separated packet types or 'all'
|
|
responses:
|
|
'200':
|
|
description: Packet type graph data
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
start_time:
|
|
type: integer
|
|
end_time:
|
|
type: integer
|
|
step:
|
|
type: integer
|
|
chart_type:
|
|
type: string
|
|
example: bar
|
|
series:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
data:
|
|
type: array
|
|
items:
|
|
type: number
|
|
|
|
/metrics_graph_data:
|
|
get:
|
|
tags: [Charts]
|
|
summary: Get system metrics graph data
|
|
description: |
|
|
Returns time-series data for system metrics like packet counts, RSSI, SNR, etc.
|
|
|
|
Available metrics:
|
|
- rx_count: Received packets
|
|
- tx_count: Transmitted packets
|
|
- drop_count: Dropped packets
|
|
- avg_rssi: Average RSSI (dBm)
|
|
- avg_snr: Average SNR (dB)
|
|
- avg_length: Average packet length
|
|
- avg_score: Average score
|
|
- neighbor_count: Neighbor count
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
- name: resolution
|
|
in: query
|
|
schema:
|
|
type: string
|
|
enum: [average, max, min]
|
|
default: average
|
|
- name: metrics
|
|
in: query
|
|
schema:
|
|
type: string
|
|
default: all
|
|
description: Comma-separated metric names or 'all'
|
|
example: "rx_count,tx_count,avg_rssi"
|
|
responses:
|
|
'200':
|
|
description: Metrics graph data
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
start_time:
|
|
type: integer
|
|
end_time:
|
|
type: integer
|
|
step:
|
|
type: integer
|
|
timestamps:
|
|
type: array
|
|
items:
|
|
type: integer
|
|
series:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
data:
|
|
type: array
|
|
items:
|
|
type: number
|
|
|
|
/noise_floor_history:
|
|
get:
|
|
tags: [Noise Floor]
|
|
summary: Get noise floor history
|
|
description: Retrieve historical noise floor measurements
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
minimum: 1
|
|
maximum: 168
|
|
description: Time range in hours
|
|
responses:
|
|
'200':
|
|
description: Noise floor history
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: array
|
|
items:
|
|
type: object
|
|
|
|
/noise_floor_stats:
|
|
get:
|
|
tags: [Noise Floor]
|
|
summary: Get noise floor statistics
|
|
description: Statistical analysis of noise floor measurements
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
responses:
|
|
'200':
|
|
description: Noise floor statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
min:
|
|
type: number
|
|
max:
|
|
type: number
|
|
avg:
|
|
type: number
|
|
current:
|
|
type: number
|
|
|
|
/noise_floor_chart_data:
|
|
get:
|
|
tags: [Noise Floor]
|
|
summary: Get noise floor chart data
|
|
description: Formatted noise floor data for charting
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
responses:
|
|
'200':
|
|
description: Chart-ready noise floor data
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
# ============================================================================
|
|
# CAD Calibration Endpoints
|
|
# ============================================================================
|
|
/cad_calibration_start:
|
|
post:
|
|
tags: [CAD Calibration]
|
|
summary: Start CAD calibration
|
|
description: Begin Channel Activity Detection calibration process
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
samples:
|
|
type: integer
|
|
default: 8
|
|
minimum: 1
|
|
maximum: 64
|
|
description: Number of samples to collect
|
|
example: 8
|
|
delay:
|
|
type: integer
|
|
default: 100
|
|
minimum: 10
|
|
maximum: 1000
|
|
description: Delay between samples in milliseconds
|
|
example: 100
|
|
examples:
|
|
default:
|
|
value:
|
|
samples: 8
|
|
delay: 100
|
|
detailed:
|
|
value:
|
|
samples: 16
|
|
delay: 50
|
|
responses:
|
|
'200':
|
|
description: Calibration started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/cad_calibration_stop:
|
|
post:
|
|
tags: [CAD Calibration]
|
|
summary: Stop CAD calibration
|
|
responses:
|
|
'200':
|
|
description: Calibration stopped
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/save_cad_settings:
|
|
post:
|
|
tags: [CAD Calibration]
|
|
summary: Save CAD settings
|
|
description: Save calibrated CAD peak and min values to configuration
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [peak, min_val]
|
|
properties:
|
|
peak:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 255
|
|
description: CAD peak value
|
|
example: 127
|
|
min_val:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 255
|
|
description: CAD minimum value
|
|
example: 64
|
|
responses:
|
|
'200':
|
|
description: Settings saved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/cad_calibration_stream:
|
|
get:
|
|
tags: [CAD Calibration]
|
|
summary: CAD calibration SSE stream
|
|
description: Server-Sent Events stream of calibration progress
|
|
responses:
|
|
'200':
|
|
description: SSE stream
|
|
content:
|
|
text/event-stream:
|
|
schema:
|
|
type: string
|
|
|
|
# ============================================================================
|
|
# Adverts & Contacts
|
|
# ============================================================================
|
|
/adverts_by_contact_type:
|
|
get:
|
|
tags: [Adverts]
|
|
summary: Get adverts by contact type
|
|
description: Retrieve advertisements filtered by contact type
|
|
parameters:
|
|
- name: contact_type
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
description: Contact type to filter by
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 100
|
|
description: Maximum number of results
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
description: Time range in hours
|
|
responses:
|
|
'200':
|
|
description: Filtered adverts
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/advert:
|
|
delete:
|
|
tags: [Adverts]
|
|
summary: Delete specific advert
|
|
description: Delete a specific advertisement by ID
|
|
parameters:
|
|
- name: advert_id
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
description: Advert ID to delete
|
|
responses:
|
|
'200':
|
|
description: Advert deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
# ============================================================================
|
|
# Transport Keys
|
|
# ============================================================================
|
|
/transport_keys:
|
|
get:
|
|
tags: [Transport Keys]
|
|
summary: List transport keys
|
|
description: Get list of all transport encryption keys
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: List of transport keys
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: array
|
|
items:
|
|
type: object
|
|
post:
|
|
tags: [Transport Keys]
|
|
summary: Create transport key
|
|
description: Generate a new transport encryption key
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: Key name/identifier
|
|
responses:
|
|
'200':
|
|
description: Key created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/transport_key:
|
|
get:
|
|
tags: [Transport Keys]
|
|
summary: Get transport key
|
|
description: Retrieve specific transport key details
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: key_id
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Key ID to retrieve
|
|
responses:
|
|
'200':
|
|
description: Key details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
put:
|
|
tags: [Transport Keys]
|
|
summary: Update transport key
|
|
description: Update an existing transport encryption key
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: key_id
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Key ID to update
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: Updated key name
|
|
flood_policy:
|
|
type: string
|
|
enum: [allow, deny]
|
|
description: Updated flood policy
|
|
transport_key:
|
|
type: string
|
|
description: Updated transport key hex
|
|
parent_id:
|
|
type: integer
|
|
nullable: true
|
|
description: Updated parent transport key ID
|
|
last_used:
|
|
type: string
|
|
format: date-time
|
|
description: Updated last-used timestamp in ISO-8601 format
|
|
responses:
|
|
'200':
|
|
description: Key updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
delete:
|
|
tags: [Transport Keys]
|
|
summary: Delete transport key
|
|
description: Remove a transport encryption key
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: key_id
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Key ID to delete
|
|
responses:
|
|
'200':
|
|
description: Key deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
# ============================================================================
|
|
# Network Policy
|
|
# ============================================================================
|
|
/unscoped_flood_policy:
|
|
post:
|
|
tags: [Network Policy]
|
|
summary: Update unscoped flood policy
|
|
description: Modify network flood policy settings
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Policy updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/ping_neighbor:
|
|
post:
|
|
tags: [Network Policy]
|
|
summary: Ping neighbor node
|
|
description: Send ping to a specific neighbor node
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [target_id]
|
|
properties:
|
|
target_id:
|
|
type: string
|
|
description: Target node identifier
|
|
timeout:
|
|
type: integer
|
|
description: Ping timeout in seconds
|
|
default: 10
|
|
responses:
|
|
'200':
|
|
description: Ping sent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
required: [target_id, rtt_ms, snr_db, rssi, path, tag]
|
|
properties:
|
|
target_id:
|
|
type: string
|
|
rtt_ms:
|
|
type: number
|
|
snr_db:
|
|
type: number
|
|
rssi:
|
|
type: number
|
|
path:
|
|
type: array
|
|
items:
|
|
type: string
|
|
tag:
|
|
type: integer
|
|
path_hash_mode:
|
|
type: integer
|
|
message:
|
|
type: string
|
|
error:
|
|
type: string
|
|
|
|
/policy:
|
|
get:
|
|
tags: [Network Policy]
|
|
summary: Get policy document
|
|
description: Returns normalized policy engine configuration and grouped channel hash/pubkey entries.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
responses:
|
|
'200':
|
|
description: Policy document
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
policy_file:
|
|
type: string
|
|
exists:
|
|
type: boolean
|
|
policy_engine:
|
|
type: object
|
|
groups:
|
|
type: object
|
|
post:
|
|
tags: [Network Policy]
|
|
summary: Update policy document
|
|
description: Update policy_engine configuration while preserving or replacing named groups.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
description: Accepts either root-level policy_engine fields or a nested policy_engine object.
|
|
responses:
|
|
'200':
|
|
description: Policy updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/policy_validate:
|
|
post:
|
|
tags: [Network Policy]
|
|
summary: Validate policy payload
|
|
description: Validate a policy payload without saving it to disk.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Validation result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
valid:
|
|
type: boolean
|
|
normalized:
|
|
type: object
|
|
effective:
|
|
type: object
|
|
|
|
/policy_groups:
|
|
get:
|
|
tags: [Network Policy]
|
|
summary: List policy groups
|
|
description: List named channel hash and pubkey groups.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: kind
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
enum: [channel_hashes, pubkeys]
|
|
description: Optional group kind filter.
|
|
responses:
|
|
'200':
|
|
description: Policy groups
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
post:
|
|
tags: [Network Policy]
|
|
summary: Create policy group
|
|
description: Create a named group for channel hashes or pubkeys.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [kind]
|
|
properties:
|
|
kind:
|
|
type: string
|
|
enum: [channel_hashes, pubkeys]
|
|
group_id:
|
|
type: string
|
|
friendly_name:
|
|
type: string
|
|
description:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Group created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
delete:
|
|
tags: [Network Policy]
|
|
summary: Delete policy group
|
|
description: Delete a named group and all of its entries.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [kind, group_id]
|
|
properties:
|
|
kind:
|
|
type: string
|
|
enum: [channel_hashes, pubkeys]
|
|
group_id:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Group deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/policy_group_entries:
|
|
get:
|
|
tags: [Network Policy]
|
|
summary: List group entries
|
|
description: Return entries for a specific named channel hash/pubkey group.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: kind
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
enum: [channel_hashes, pubkeys]
|
|
- name: group_id
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Group entries
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
post:
|
|
tags: [Network Policy]
|
|
summary: Add group entry
|
|
description: Add a friendly-named entry to a policy group.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [kind, group_id, value]
|
|
properties:
|
|
kind:
|
|
type: string
|
|
enum: [channel_hashes, pubkeys]
|
|
group_id:
|
|
type: string
|
|
value:
|
|
type: string
|
|
entry_id:
|
|
type: string
|
|
friendly_name:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Entry added
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
delete:
|
|
tags: [Network Policy]
|
|
summary: Remove group entry
|
|
description: Remove an entry by entry_id or value from a policy group.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [kind, group_id]
|
|
properties:
|
|
kind:
|
|
type: string
|
|
enum: [channel_hashes, pubkeys]
|
|
group_id:
|
|
type: string
|
|
entry_id:
|
|
type: string
|
|
value:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Entry removed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
# ============================================================================
|
|
# Identity Management
|
|
# ============================================================================
|
|
/create_identity:
|
|
post:
|
|
tags: [Identities]
|
|
summary: Create new identity
|
|
description: |
|
|
Create a new companion or room server identity.
|
|
`name` must be non-empty after trimming leading/trailing whitespace (whitespace-only values are rejected).
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name, type]
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 64
|
|
pattern: '^[a-zA-Z0-9_\-\s]+$'
|
|
description: |
|
|
Identity registration name (alphanumeric, spaces, hyphens, underscores).
|
|
Trimmed; must not be empty or whitespace-only.
|
|
example: "General Chat"
|
|
identity_key:
|
|
type: string
|
|
pattern: '^(?:[0-9a-fA-F]{64}|[0-9a-fA-F]{128})$'
|
|
description: 32- or 64-byte hex key (64 or 128 chars). Omit for auto-generation
|
|
example: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
type:
|
|
type: string
|
|
enum: [companion, room_server]
|
|
description: |
|
|
- companion: Companion identity with a TCP endpoint
|
|
- room_server: Room server for group chat
|
|
example: room_server
|
|
settings:
|
|
type: object
|
|
description: Type-specific settings
|
|
properties:
|
|
admin_password:
|
|
type: string
|
|
minLength: 4
|
|
description: Admin authentication password (room_server only)
|
|
example: "admin123"
|
|
guest_password:
|
|
type: string
|
|
minLength: 4
|
|
description: Guest authentication password (room_server only)
|
|
example: "guest123"
|
|
max_posts:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 32
|
|
default: 32
|
|
description: Maximum messages to keep (hard limit 32)
|
|
example: 32
|
|
node_name:
|
|
type: string
|
|
description: Advertised node name (companion only; defaults to identity name)
|
|
example: "My Companion"
|
|
tcp_port:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 65535
|
|
default: 5000
|
|
description: TCP listener port (companion only)
|
|
example: 5000
|
|
bind_address:
|
|
type: string
|
|
default: "0.0.0.0"
|
|
description: TCP listener bind address (companion only)
|
|
example: "0.0.0.0"
|
|
examples:
|
|
room_server:
|
|
value:
|
|
name: "General Chat"
|
|
type: room_server
|
|
settings:
|
|
admin_password: "admin123"
|
|
guest_password: "guest123"
|
|
max_posts: 32
|
|
companion:
|
|
value:
|
|
name: "My Companion"
|
|
type: companion
|
|
identity_key: "aaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaaa"
|
|
settings:
|
|
node_name: "My Companion"
|
|
tcp_port: 5000
|
|
bind_address: "0.0.0.0"
|
|
responses:
|
|
'200':
|
|
description: Identity created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
type:
|
|
type: string
|
|
hash:
|
|
type: string
|
|
public_key:
|
|
type: string
|
|
examples:
|
|
success:
|
|
value:
|
|
success: true
|
|
data:
|
|
name: "General Chat"
|
|
type: room_server
|
|
hash: "0x42"
|
|
public_key: "abc123..."
|
|
'400':
|
|
description: Invalid parameters
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/identities:
|
|
get:
|
|
tags: [Identities]
|
|
summary: List all identities
|
|
description: |
|
|
Returns configured room servers and companions plus runtime registration info.
|
|
Companion entries with missing or blank registration names are assigned a stable
|
|
`companion_<pubkeyPrefix>` name derived from the identity key and persisted when possible.
|
|
responses:
|
|
'200':
|
|
description: List of identities
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
identities:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/Identity'
|
|
|
|
/identity:
|
|
get:
|
|
tags: [Identities]
|
|
summary: Get specific identity
|
|
description: Retrieve details of a specific identity by name
|
|
parameters:
|
|
- name: name
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
description: Identity name to retrieve
|
|
responses:
|
|
'200':
|
|
description: Identity details
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
$ref: '#/components/schemas/Identity'
|
|
|
|
/update_identity:
|
|
put:
|
|
tags: [Identities]
|
|
summary: Update identity
|
|
description: |
|
|
Modify an existing identity's configuration.
|
|
For `room_server`, `name` is required to locate the identity.
|
|
For `companion`, provide `name` OR `lookup_identity_key` OR `public_key_prefix`
|
|
(at least 8 hex characters for prefix lookups) when the registration name is unknown.
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
type:
|
|
type: string
|
|
enum: [room_server, companion]
|
|
default: room_server
|
|
name:
|
|
type: string
|
|
description: Current identity registration name (required for room_server; optional for companion if lookup fields are set)
|
|
lookup_identity_key:
|
|
type: string
|
|
description: |
|
|
Companion only: hex private identity key (full or unique prefix, min 8 hex chars)
|
|
to locate the companion when `name` is omitted.
|
|
public_key_prefix:
|
|
type: string
|
|
description: |
|
|
Companion only: ed25519 public key hex prefix (min 8 hex chars) to locate the companion when `name` is omitted.
|
|
new_name:
|
|
type: string
|
|
description: New identity name (optional; must be non-empty if provided)
|
|
identity_key:
|
|
type: string
|
|
description: New identity key (optional)
|
|
settings:
|
|
type: object
|
|
description: Updated settings
|
|
responses:
|
|
'200':
|
|
description: Identity updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/delete_identity:
|
|
delete:
|
|
tags: [Identities]
|
|
summary: Delete identity
|
|
description: |
|
|
Remove an identity from the system.
|
|
For `room_server`, `name` is required.
|
|
For `companion`, provide `name` OR `lookup_identity_key` OR `public_key_prefix`
|
|
(at least 8 hex characters for prefix lookups).
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
parameters:
|
|
- name: name
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
description: Identity registration name to delete (required for room_server)
|
|
- name: type
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
enum: [room_server, companion]
|
|
description: Identity kind (default room_server)
|
|
- name: lookup_identity_key
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
description: |
|
|
Companion only: hex identity key (full or unique prefix, min 8 hex chars) when `name` is omitted.
|
|
- name: public_key_prefix
|
|
in: query
|
|
required: false
|
|
schema:
|
|
type: string
|
|
description: |
|
|
Companion only: public key hex prefix (min 8 hex chars) when `name` is omitted.
|
|
responses:
|
|
'200':
|
|
description: Identity deleted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/send_room_server_advert:
|
|
post:
|
|
tags: [Identities]
|
|
summary: Send room server advertisement
|
|
description: Broadcast a room server advertisement packet
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [name]
|
|
properties:
|
|
name:
|
|
type: string
|
|
description: Room server identity name
|
|
node_name:
|
|
type: string
|
|
description: Node name for the advertisement
|
|
latitude:
|
|
type: number
|
|
format: float
|
|
description: GPS latitude
|
|
example: 0.0
|
|
longitude:
|
|
type: number
|
|
format: float
|
|
description: GPS longitude
|
|
example: 0.0
|
|
disable_fwd:
|
|
type: boolean
|
|
description: Disable forwarding flag
|
|
default: false
|
|
responses:
|
|
'200':
|
|
description: Advertisement sent
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
# ============================================================================
|
|
# ACL (Access Control List)
|
|
# ============================================================================
|
|
/acl_info:
|
|
get:
|
|
tags: [ACL]
|
|
summary: Get ACL information for all identities
|
|
description: |
|
|
Get ACL configuration and statistics for all registered identities.
|
|
|
|
Returns information including:
|
|
- Identity name, type, and hash
|
|
- Max clients allowed
|
|
- Number of authenticated clients
|
|
- Password configuration status
|
|
- Read-only access setting
|
|
responses:
|
|
'200':
|
|
description: ACL information for all identities
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
acls:
|
|
type: array
|
|
items:
|
|
type: object
|
|
properties:
|
|
name:
|
|
type: string
|
|
example: "repeater"
|
|
type:
|
|
type: string
|
|
enum: [repeater, room_server]
|
|
example: "repeater"
|
|
hash:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
example: "0x42"
|
|
max_clients:
|
|
type: integer
|
|
example: 100
|
|
authenticated_clients:
|
|
type: integer
|
|
example: 5
|
|
has_admin_password:
|
|
type: boolean
|
|
example: true
|
|
has_guest_password:
|
|
type: boolean
|
|
example: true
|
|
allow_read_only:
|
|
type: boolean
|
|
example: true
|
|
total_identities:
|
|
type: integer
|
|
example: 3
|
|
total_authenticated_clients:
|
|
type: integer
|
|
example: 15
|
|
|
|
/acl_clients:
|
|
get:
|
|
tags: [ACL]
|
|
summary: List ACL clients
|
|
description: Get list of authenticated clients in access control list for an identity
|
|
parameters:
|
|
- name: identity_hash
|
|
in: query
|
|
schema:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Identity hash
|
|
example: "0x42"
|
|
- name: identity_name
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Identity name
|
|
example: "General"
|
|
responses:
|
|
'200':
|
|
description: ACL clients list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
clients:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/ACLClient'
|
|
count:
|
|
type: integer
|
|
description: Number of clients returned
|
|
filter:
|
|
type: string
|
|
nullable: true
|
|
description: Filter applied (if any)
|
|
examples:
|
|
success:
|
|
value:
|
|
success: true
|
|
data:
|
|
clients:
|
|
- public_key: "03ccf3bb0bed9a51...21416fff"
|
|
public_key_full: "03ccf3bb0bed9a5109868a1e33ed020519aab6dbb30e42df3b11a21d21416fff"
|
|
address: "e1"
|
|
permissions: "admin"
|
|
last_activity: 1766065148
|
|
last_login_success: 1766065146
|
|
last_timestamp: 1766065146
|
|
identity_name: "rrrrr"
|
|
identity_type: "room_server"
|
|
identity_hash: "0xC5"
|
|
count: 1
|
|
filter: null
|
|
|
|
/acl_remove_client:
|
|
post:
|
|
tags: [ACL]
|
|
summary: Remove client from ACL
|
|
description: Remove a client from the access control list
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [identity_hash, client_pubkey]
|
|
properties:
|
|
identity_hash:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Identity hash
|
|
example: "0x42"
|
|
identity_name:
|
|
type: string
|
|
description: Identity name (alternative to hash)
|
|
example: "General"
|
|
client_pubkey:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{64}$'
|
|
description: Client public key to remove
|
|
example: "abc123def456..."
|
|
responses:
|
|
'200':
|
|
description: Client removed from ACL
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/acl_stats:
|
|
get:
|
|
tags: [ACL]
|
|
summary: Get ACL statistics
|
|
description: Get statistics about access control lists
|
|
responses:
|
|
'200':
|
|
description: ACL statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
total_entries:
|
|
type: integer
|
|
by_identity:
|
|
type: object
|
|
|
|
/room_messages:
|
|
get:
|
|
tags: [Room Server]
|
|
summary: Get room messages
|
|
description: |
|
|
Retrieve messages from a room with pagination.
|
|
|
|
**Max Messages Per Room**: 32 (hard limit)
|
|
- Older messages auto-deleted every 10 minutes
|
|
- Cannot be increased beyond 32
|
|
parameters:
|
|
- name: room_name
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Name of the room (use this OR room_hash)
|
|
example: General
|
|
- name: room_hash
|
|
in: query
|
|
schema:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Hash of room identity (use this OR room_name)
|
|
example: "0x42"
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50
|
|
minimum: 1
|
|
maximum: 100
|
|
description: Max messages to return
|
|
example: 50
|
|
- name: offset
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 0
|
|
minimum: 0
|
|
description: Skip first N messages (for pagination)
|
|
example: 0
|
|
- name: since_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
format: float
|
|
description: Only return messages after this Unix timestamp
|
|
example: 1734567890.5
|
|
responses:
|
|
'200':
|
|
description: Messages retrieved
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
room_name:
|
|
type: string
|
|
room_hash:
|
|
type: string
|
|
messages:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RoomMessage'
|
|
count:
|
|
type: integer
|
|
description: Number of messages in this response
|
|
total:
|
|
type: integer
|
|
description: Total messages in room (max 32)
|
|
limit:
|
|
type: integer
|
|
offset:
|
|
type: integer
|
|
examples:
|
|
success:
|
|
value:
|
|
success: true
|
|
data:
|
|
room_name: "General"
|
|
room_hash: "0x42"
|
|
messages:
|
|
- id: 123
|
|
author_pubkey: "abc123def456..."
|
|
author_prefix: "abc123de"
|
|
post_timestamp: 1734567890.5
|
|
sender_timestamp: 1734567890
|
|
message_text: "Hello world"
|
|
txt_type: 0
|
|
created_at: 1734567890.5
|
|
count: 1
|
|
total: 15
|
|
limit: 50
|
|
offset: 0
|
|
'404':
|
|
description: Room not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/room_post_message:
|
|
post:
|
|
tags: [Room Server]
|
|
summary: Post message to room
|
|
description: |
|
|
Add a new message to a room server. Message will be distributed to all synced clients.
|
|
|
|
**Special author values:**
|
|
- `"server"` or `"system"` - System message, goes to ALL clients (API only)
|
|
- Any hex string - Normal message, NOT sent to that client
|
|
|
|
**Security:**
|
|
- Radio messages cannot use server key (blocked)
|
|
- API messages can use server key (for announcements)
|
|
|
|
**Rate Limits:**
|
|
- 10 messages/minute per author_pubkey
|
|
- 160 bytes max message length
|
|
- Global 1.1s gap between transmissions
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [message, author_pubkey]
|
|
properties:
|
|
room_name:
|
|
type: string
|
|
description: Name of the room (use this OR room_hash)
|
|
example: General
|
|
room_hash:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Hash of room identity (use this OR room_name)
|
|
example: "0x42"
|
|
message:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 160
|
|
description: Message text (auto-truncated at 160 bytes)
|
|
example: "Hello from API"
|
|
author_pubkey:
|
|
type: string
|
|
description: |
|
|
Author's public key as hex string (64 chars), or special values:
|
|
- "server" = system message (all clients receive)
|
|
- "system" = alias for "server"
|
|
- hex string = normal message (author won't receive)
|
|
example: "abc123def456..."
|
|
txt_type:
|
|
type: integer
|
|
default: 0
|
|
enum: [0, 2]
|
|
description: |
|
|
Message type:
|
|
- 0: Plain text
|
|
- 2: Signed plain text
|
|
example: 0
|
|
examples:
|
|
normal_message:
|
|
summary: Normal message
|
|
value:
|
|
room_name: "General"
|
|
message: "Hello everyone!"
|
|
author_pubkey: "abc123def456..."
|
|
txt_type: 0
|
|
server_message:
|
|
summary: Server announcement
|
|
value:
|
|
room_name: "General"
|
|
message: "[SERVER] Maintenance in 10 minutes"
|
|
author_pubkey: "server"
|
|
by_hash:
|
|
summary: Post by room hash
|
|
value:
|
|
room_hash: "0x42"
|
|
message: "Using hash instead of name"
|
|
author_pubkey: "abc123..."
|
|
responses:
|
|
'200':
|
|
description: Message posted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
message_id:
|
|
type: integer
|
|
description: Database ID of created message
|
|
room_name:
|
|
type: string
|
|
room_hash:
|
|
type: string
|
|
queued_for_distribution:
|
|
type: boolean
|
|
description: Always true - distribution is async
|
|
is_server_message:
|
|
type: boolean
|
|
description: True if author_pubkey was "server"
|
|
author_filter_note:
|
|
type: string
|
|
description: Explains message distribution behavior
|
|
examples:
|
|
normal:
|
|
value:
|
|
success: true
|
|
data:
|
|
message_id: 124
|
|
room_name: "General"
|
|
room_hash: "0x42"
|
|
queued_for_distribution: true
|
|
is_server_message: false
|
|
author_filter_note: "Message will NOT be sent to author"
|
|
server:
|
|
value:
|
|
success: true
|
|
data:
|
|
message_id: 125
|
|
room_name: "General"
|
|
room_hash: "0x42"
|
|
queued_for_distribution: true
|
|
is_server_message: true
|
|
author_filter_note: "Server messages go to ALL clients"
|
|
'400':
|
|
description: Invalid parameters or rate limit exceeded
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
examples:
|
|
rate_limit:
|
|
value:
|
|
success: false
|
|
error: "Failed to add message (rate limit or validation error)"
|
|
missing_field:
|
|
value:
|
|
success: false
|
|
error: "message is required"
|
|
|
|
/room_stats:
|
|
get:
|
|
tags: [Room Server]
|
|
summary: Get room statistics
|
|
description: |
|
|
Get detailed statistics for one or all room servers.
|
|
|
|
**Room Limits:**
|
|
- 32 messages maximum per room (hard limit)
|
|
- Messages auto-expire every 10 minutes
|
|
- Author filtering: messages not sent back to author
|
|
parameters:
|
|
- name: room_name
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Get stats for specific room (omit for all rooms)
|
|
example: General
|
|
- name: room_hash
|
|
in: query
|
|
schema:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Get stats by room hash (use this OR room_name)
|
|
example: "0x42"
|
|
responses:
|
|
'200':
|
|
description: Room statistics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
room_name:
|
|
type: string
|
|
room_hash:
|
|
type: string
|
|
total_messages:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 32
|
|
description: Current message count (max 32)
|
|
example: 15
|
|
total_clients:
|
|
type: integer
|
|
minimum: 0
|
|
description: Total clients that have synced
|
|
example: 8
|
|
active_clients:
|
|
type: integer
|
|
minimum: 0
|
|
description: Clients active within timeout window
|
|
example: 3
|
|
max_posts:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 32
|
|
description: Message limit setting (always 32)
|
|
example: 32
|
|
sync_running:
|
|
type: boolean
|
|
description: Distribution task is active
|
|
example: true
|
|
clients:
|
|
type: array
|
|
description: List of all clients with sync status
|
|
items:
|
|
$ref: '#/components/schemas/RoomClient'
|
|
examples:
|
|
single_room:
|
|
value:
|
|
success: true
|
|
data:
|
|
room_name: "General"
|
|
room_hash: "0x42"
|
|
total_messages: 15
|
|
total_clients: 8
|
|
active_clients: 3
|
|
max_posts: 32
|
|
sync_running: true
|
|
clients:
|
|
- pubkey: "abc123..."
|
|
pubkey_prefix: "abc123de"
|
|
sync_since: 1734567890.5
|
|
unsynced_count: 5
|
|
is_active: true
|
|
all_rooms:
|
|
value:
|
|
success: true
|
|
data:
|
|
rooms:
|
|
- room_name: "General"
|
|
total_messages: 15
|
|
active_clients: 3
|
|
- room_name: "Tech"
|
|
total_messages: 8
|
|
active_clients: 1
|
|
'404':
|
|
description: Room not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/room_clients:
|
|
get:
|
|
tags: [Room Server]
|
|
summary: Get room clients
|
|
description: |
|
|
List all clients synced to a room with their status.
|
|
|
|
**Client Filtering:**
|
|
- Clients only receive messages where author_pubkey ≠ client_pubkey
|
|
- unsynced_count shows pending messages for each client
|
|
- is_active indicates client synced within timeout window
|
|
parameters:
|
|
- name: room_name
|
|
in: query
|
|
schema:
|
|
type: string
|
|
description: Room name
|
|
example: General
|
|
- name: room_hash
|
|
in: query
|
|
schema:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Room hash (use this OR room_name)
|
|
example: "0x42"
|
|
responses:
|
|
'200':
|
|
description: Client list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
room_name:
|
|
type: string
|
|
room_hash:
|
|
type: string
|
|
clients:
|
|
type: array
|
|
items:
|
|
$ref: '#/components/schemas/RoomClient'
|
|
examples:
|
|
success:
|
|
value:
|
|
success: true
|
|
data:
|
|
room_name: "General"
|
|
room_hash: "0x42"
|
|
clients:
|
|
- pubkey: "abc123def456..."
|
|
pubkey_prefix: "abc123de"
|
|
sync_since: 1734567890.5
|
|
unsynced_count: 5
|
|
pending_ack: false
|
|
push_failures: 0
|
|
last_activity: 1734567890.5
|
|
in_acl: true
|
|
is_active: true
|
|
'404':
|
|
description: Room not found
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/ErrorResponse'
|
|
|
|
/room_message:
|
|
delete:
|
|
tags: [Room Server]
|
|
summary: Delete specific message
|
|
parameters:
|
|
- name: room_name
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: room_hash
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: message_id
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Message deleted
|
|
|
|
/room_messages_clear:
|
|
delete:
|
|
tags: [Room Server]
|
|
summary: Clear all room messages
|
|
description: ⚠️ Destructive operation - cannot be undone!
|
|
parameters:
|
|
- name: room_name
|
|
in: query
|
|
schema:
|
|
type: string
|
|
- name: room_hash
|
|
in: query
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Messages cleared
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
properties:
|
|
deleted_count:
|
|
type: integer
|
|
|
|
/needs_setup:
|
|
get:
|
|
tags: [System]
|
|
summary: Check setup wizard status
|
|
responses:
|
|
'200':
|
|
description: Setup status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/site_info:
|
|
get:
|
|
tags: [System]
|
|
summary: Get site and host info
|
|
responses:
|
|
'200':
|
|
description: Site info
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/hardware_options:
|
|
get:
|
|
tags: [System]
|
|
summary: Get supported hardware options
|
|
responses:
|
|
'200':
|
|
description: Hardware options
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/radio_presets:
|
|
get:
|
|
tags: [System]
|
|
summary: Get radio presets
|
|
responses:
|
|
'200':
|
|
description: Preset list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/serial_ports:
|
|
get:
|
|
tags: [System]
|
|
summary: List available serial ports
|
|
responses:
|
|
'200':
|
|
description: Serial ports
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/setup_wizard:
|
|
post:
|
|
tags: [System]
|
|
summary: Submit setup wizard payload
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Setup applied
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/check_pymc_console:
|
|
get:
|
|
tags: [System]
|
|
summary: Check pyMC console availability
|
|
responses:
|
|
'200':
|
|
description: Console status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/mqtt_status:
|
|
get:
|
|
tags: [System]
|
|
summary: Get MQTT runtime status
|
|
responses:
|
|
'200':
|
|
description: MQTT status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/broker_presets:
|
|
get:
|
|
tags: [System]
|
|
summary: List MQTT broker presets
|
|
responses:
|
|
'200':
|
|
description: Broker presets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/update_web_config:
|
|
post:
|
|
tags: [System]
|
|
summary: Update web configuration
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Web config updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/update_mqtt_config:
|
|
post:
|
|
tags: [System]
|
|
summary: Update MQTT configuration
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: MQTT config updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/update_advert_rate_limit_config:
|
|
post:
|
|
tags: [Adverts]
|
|
summary: Update advert rate limit configuration
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Advert rate limit config updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
$ref: '#/components/schemas/SuccessResponse'
|
|
|
|
/bulk_packets:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Fetch packets in bulk
|
|
parameters:
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 1000
|
|
- name: offset
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 0
|
|
- name: start_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
- name: end_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
responses:
|
|
'200':
|
|
description: Bulk packet result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/airtime_data:
|
|
get:
|
|
tags: [Packets]
|
|
summary: Get lightweight airtime packet rows
|
|
parameters:
|
|
- name: start_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
- name: end_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 50000
|
|
responses:
|
|
'200':
|
|
description: Airtime data rows
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/airtime_chart_data:
|
|
get:
|
|
tags: [Charts]
|
|
summary: Get server-aggregated airtime chart buckets
|
|
parameters:
|
|
- name: start_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
- name: end_timestamp
|
|
in: query
|
|
schema:
|
|
type: number
|
|
- name: bucket_seconds
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 60
|
|
- name: sf
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 9
|
|
- name: bw_hz
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 62500
|
|
- name: cr
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 5
|
|
- name: preamble
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 17
|
|
responses:
|
|
'200':
|
|
description: Airtime buckets
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/adverts_count_by_contact_type:
|
|
get:
|
|
tags: [Adverts]
|
|
summary: Get advert count for contact type
|
|
parameters:
|
|
- name: contact_type
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Advert count
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/advert_rate_limit_stats:
|
|
get:
|
|
tags: [Adverts]
|
|
summary: Get advert rate-limit runtime stats
|
|
responses:
|
|
'200':
|
|
description: Rate-limit stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/crc_error_count:
|
|
get:
|
|
tags: [System]
|
|
summary: Get CRC error count
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
responses:
|
|
'200':
|
|
description: CRC error count
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/crc_error_history:
|
|
get:
|
|
tags: [System]
|
|
summary: Get CRC error history
|
|
parameters:
|
|
- name: hours
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
default: 24
|
|
- name: limit
|
|
in: query
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: CRC error records
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/memory_debug:
|
|
get:
|
|
tags: [System]
|
|
summary: Get memory diagnostics
|
|
responses:
|
|
'200':
|
|
description: Memory diagnostics
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
post:
|
|
tags: [System]
|
|
summary: Start/stop memory diagnostics tracing
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
properties:
|
|
action:
|
|
type: string
|
|
enum: [start, stop]
|
|
responses:
|
|
'200':
|
|
description: Tracing state changed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/config_export:
|
|
get:
|
|
tags: [System]
|
|
summary: Export configuration
|
|
parameters:
|
|
- name: include_secrets
|
|
in: query
|
|
schema:
|
|
type: boolean
|
|
responses:
|
|
'200':
|
|
description: Exported config payload
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
required: [meta, config]
|
|
properties:
|
|
meta:
|
|
type: object
|
|
required: [exported_at, version, config_path, includes_secrets]
|
|
properties:
|
|
exported_at:
|
|
type: string
|
|
format: date-time
|
|
version:
|
|
type: string
|
|
config_path:
|
|
type: string
|
|
includes_secrets:
|
|
type: boolean
|
|
config:
|
|
type: object
|
|
error:
|
|
type: string
|
|
|
|
/config_import:
|
|
post:
|
|
tags: [System]
|
|
summary: Import configuration
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Import result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/identity_export:
|
|
get:
|
|
tags: [Identities]
|
|
summary: Export repeater identity key
|
|
responses:
|
|
'200':
|
|
description: Identity export
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
required: [identity_key_hex, key_length_bytes]
|
|
properties:
|
|
identity_key_hex:
|
|
type: string
|
|
key_length_bytes:
|
|
type: integer
|
|
public_key_hex:
|
|
type: string
|
|
node_address:
|
|
type: string
|
|
error:
|
|
type: string
|
|
|
|
/generate_vanity_key:
|
|
post:
|
|
tags: [Identities]
|
|
summary: Generate vanity identity key
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [prefix]
|
|
properties:
|
|
prefix:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 8
|
|
apply:
|
|
type: boolean
|
|
responses:
|
|
'200':
|
|
description: Vanity key generation result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
required: [public_hex, private_hex, attempts]
|
|
properties:
|
|
public_hex:
|
|
type: string
|
|
private_hex:
|
|
type: string
|
|
attempts:
|
|
type: integer
|
|
applied:
|
|
type: boolean
|
|
error:
|
|
type: string
|
|
|
|
/db_stats:
|
|
get:
|
|
tags: [System]
|
|
summary: Get database statistics
|
|
responses:
|
|
'200':
|
|
description: Database stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
required: [database_size_bytes, rrd_size_bytes, tables]
|
|
properties:
|
|
database_size_bytes:
|
|
type: integer
|
|
rrd_size_bytes:
|
|
type: integer
|
|
tables:
|
|
type: array
|
|
items:
|
|
type: object
|
|
required: [name, row_count, has_timestamp]
|
|
properties:
|
|
name:
|
|
type: string
|
|
row_count:
|
|
type: integer
|
|
oldest_timestamp:
|
|
type: number
|
|
newest_timestamp:
|
|
type: number
|
|
has_timestamp:
|
|
type: boolean
|
|
error:
|
|
type: string
|
|
|
|
/db_purge:
|
|
post:
|
|
tags: [System]
|
|
summary: Purge database tables
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Table purge result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data, message]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
additionalProperties:
|
|
type: object
|
|
properties:
|
|
deleted:
|
|
type: integer
|
|
error:
|
|
type: string
|
|
message:
|
|
type: string
|
|
error:
|
|
type: string
|
|
|
|
/db_vacuum:
|
|
post:
|
|
tags: [System]
|
|
summary: Vacuum SQLite database
|
|
responses:
|
|
'200':
|
|
description: Vacuum result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [success, data]
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
data:
|
|
type: object
|
|
required: [size_before, size_after, freed_bytes]
|
|
properties:
|
|
size_before:
|
|
type: integer
|
|
size_after:
|
|
type: integer
|
|
freed_bytes:
|
|
type: integer
|
|
error:
|
|
type: string
|
|
|
|
/docs:
|
|
get:
|
|
tags: [System]
|
|
summary: Serve Swagger UI docs page
|
|
responses:
|
|
'200':
|
|
description: HTML docs page
|
|
|
|
/api/auth/tokens:
|
|
get:
|
|
tags: [Authentication]
|
|
summary: List API tokens (alias path)
|
|
responses:
|
|
'200':
|
|
description: Token list
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
post:
|
|
tags: [Authentication]
|
|
summary: Create API token (alias path)
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Token created
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/api/auth/tokens/{token_id}:
|
|
delete:
|
|
tags: [Authentication]
|
|
summary: Revoke API token (alias path)
|
|
parameters:
|
|
- name: token_id
|
|
in: path
|
|
required: true
|
|
schema:
|
|
type: integer
|
|
responses:
|
|
'200':
|
|
description: Token revoked
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion:
|
|
get:
|
|
tags: [System]
|
|
summary: List companion bridge instances
|
|
responses:
|
|
'200':
|
|
description: Companion instances
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/self_info:
|
|
get:
|
|
tags: [System]
|
|
summary: Get local companion identity info
|
|
responses:
|
|
'200':
|
|
description: Companion identity
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/contacts:
|
|
get:
|
|
tags: [System]
|
|
summary: List companion contacts
|
|
responses:
|
|
'200':
|
|
description: Contacts
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/contact:
|
|
get:
|
|
tags: [System]
|
|
summary: Get one companion contact
|
|
parameters:
|
|
- name: pub_key
|
|
in: query
|
|
required: true
|
|
schema:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: Contact detail
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/import_repeater_contacts:
|
|
post:
|
|
tags: [System]
|
|
summary: Import repeater adverts into companion contacts
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Import result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/channels:
|
|
get:
|
|
tags: [System]
|
|
summary: List companion channels
|
|
responses:
|
|
'200':
|
|
description: Channels
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/stats:
|
|
get:
|
|
tags: [System]
|
|
summary: Get companion stats
|
|
responses:
|
|
'200':
|
|
description: Companion stats
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/send_text:
|
|
post:
|
|
tags: [System]
|
|
summary: Send direct text message via companion
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Send result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/send_channel_message:
|
|
post:
|
|
tags: [System]
|
|
summary: Send channel message via companion
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Send result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/login:
|
|
post:
|
|
tags: [System]
|
|
summary: Initiate companion login flow
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Login result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/request_status:
|
|
post:
|
|
tags: [System]
|
|
summary: Request companion status frame
|
|
responses:
|
|
'200':
|
|
description: Request accepted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/request_telemetry:
|
|
post:
|
|
tags: [System]
|
|
summary: Request companion telemetry frame
|
|
responses:
|
|
'200':
|
|
description: Request accepted
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/send_command:
|
|
post:
|
|
tags: [System]
|
|
summary: Send command to companion
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Command result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/reset_path:
|
|
post:
|
|
tags: [System]
|
|
summary: Reset companion route/path state
|
|
responses:
|
|
'200':
|
|
description: Path reset
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/set_advert_name:
|
|
post:
|
|
tags: [System]
|
|
summary: Set companion advert name
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Name updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/set_advert_location:
|
|
post:
|
|
tags: [System]
|
|
summary: Set companion advert location
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Location updated
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/companion/events:
|
|
get:
|
|
tags: [System]
|
|
summary: Stream companion events (SSE)
|
|
responses:
|
|
'200':
|
|
description: Event stream
|
|
|
|
/update/status:
|
|
get:
|
|
tags: [System]
|
|
summary: Get update service status
|
|
responses:
|
|
'200':
|
|
description: Update status
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/update/check:
|
|
get:
|
|
tags: [System]
|
|
summary: Trigger or fetch update check
|
|
responses:
|
|
'200':
|
|
description: Check result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
post:
|
|
tags: [System]
|
|
summary: Trigger update check
|
|
requestBody:
|
|
required: false
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Check started/result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/update/install:
|
|
post:
|
|
tags: [System]
|
|
summary: Install available update
|
|
requestBody:
|
|
required: false
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Install started
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/update/progress:
|
|
get:
|
|
tags: [System]
|
|
summary: Stream update progress (SSE)
|
|
responses:
|
|
'200':
|
|
description: Progress event stream
|
|
|
|
/update/channels:
|
|
get:
|
|
tags: [System]
|
|
summary: List update channels
|
|
responses:
|
|
'200':
|
|
description: Available channels
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/update/set_channel:
|
|
post:
|
|
tags: [System]
|
|
summary: Set update channel
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
responses:
|
|
'200':
|
|
description: Channel changed
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/update/changelog:
|
|
get:
|
|
tags: [System]
|
|
summary: Get update changelog
|
|
responses:
|
|
'200':
|
|
description: Changelog content
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
/cli:
|
|
post:
|
|
tags: [System]
|
|
summary: Execute repeater CLI command
|
|
security:
|
|
- BearerAuth: []
|
|
- ApiKeyAuth: []
|
|
requestBody:
|
|
required: true
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
required: [command]
|
|
properties:
|
|
command:
|
|
type: string
|
|
responses:
|
|
'200':
|
|
description: CLI command result
|
|
content:
|
|
application/json:
|
|
schema:
|
|
type: object
|
|
|
|
components:
|
|
schemas:
|
|
SuccessResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: true
|
|
data:
|
|
type: object
|
|
description: Response data (varies by endpoint)
|
|
|
|
ErrorResponse:
|
|
type: object
|
|
properties:
|
|
success:
|
|
type: boolean
|
|
example: false
|
|
error:
|
|
type: string
|
|
description: Error message
|
|
|
|
RoomMessage:
|
|
type: object
|
|
required: [id, author_pubkey, post_timestamp, message_text, txt_type]
|
|
properties:
|
|
id:
|
|
type: integer
|
|
description: Database message ID
|
|
example: 123
|
|
author_pubkey:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{64}$|^00{64}$'
|
|
description: |
|
|
Author's public key (64 hex chars):
|
|
- 32 zeros (64 '0's) = server/system message
|
|
- Other hex = regular user message
|
|
example: "abc123def456..."
|
|
author_prefix:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{8}$'
|
|
description: First 8 chars of author_pubkey (for display)
|
|
example: "abc123de"
|
|
post_timestamp:
|
|
type: number
|
|
format: float
|
|
description: Server timestamp when message was stored (Unix epoch)
|
|
example: 1734567890.5
|
|
sender_timestamp:
|
|
type: integer
|
|
description: Client-provided timestamp (may be inaccurate)
|
|
example: 1734567890
|
|
message_text:
|
|
type: string
|
|
maxLength: 160
|
|
description: Message content (auto-truncated at 160 bytes)
|
|
example: "Hello world"
|
|
txt_type:
|
|
type: integer
|
|
enum: [0, 2]
|
|
description: |
|
|
Message type:
|
|
- 0: Plain text
|
|
- 2: Signed plain text
|
|
example: 0
|
|
created_at:
|
|
type: number
|
|
format: float
|
|
description: Database insertion timestamp (Unix epoch)
|
|
example: 1734567890.5
|
|
|
|
RoomClient:
|
|
type: object
|
|
required: [pubkey, sync_since, unsynced_count, is_active]
|
|
properties:
|
|
pubkey:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{64}$'
|
|
description: Client's public key (64 hex chars)
|
|
example: "abc123def456..."
|
|
pubkey_prefix:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{8}$'
|
|
description: First 8 chars of pubkey (for display)
|
|
example: "abc123de"
|
|
sync_since:
|
|
type: number
|
|
format: float
|
|
description: Last sync timestamp (Unix epoch)
|
|
example: 1734567890.5
|
|
unsynced_count:
|
|
type: integer
|
|
minimum: 0
|
|
maximum: 32
|
|
description: Number of new messages for this client (max 32, messages NOT sent to author)
|
|
example: 5
|
|
pending_ack:
|
|
type: boolean
|
|
description: Waiting for ACK from client
|
|
example: false
|
|
push_failures:
|
|
type: integer
|
|
minimum: 0
|
|
description: Number of failed delivery attempts
|
|
example: 0
|
|
last_activity:
|
|
type: number
|
|
format: float
|
|
description: Last activity timestamp (Unix epoch)
|
|
example: 1734567890.5
|
|
in_acl:
|
|
type: boolean
|
|
description: Client passes ACL check
|
|
example: true
|
|
is_active:
|
|
type: boolean
|
|
description: Client is currently active (synced within timeout period)
|
|
example: true
|
|
|
|
Identity:
|
|
type: object
|
|
required: [name, type, hash, public_key]
|
|
properties:
|
|
name:
|
|
type: string
|
|
minLength: 1
|
|
maxLength: 64
|
|
pattern: '^[a-zA-Z0-9_\-\s]+$'
|
|
description: Identity name (alphanumeric, spaces, hyphens, underscores)
|
|
example: "General Chat"
|
|
type:
|
|
type: string
|
|
enum: [repeater, room_server]
|
|
description: |
|
|
- repeater: Repeater identity (only one allowed per system)
|
|
- room_server: Room server for group chat
|
|
example: room_server
|
|
hash:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: 1-byte identity hash (used in radio packets)
|
|
example: "0x42"
|
|
public_key:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{64}$'
|
|
description: Ed25519 public key (64 hex chars)
|
|
example: "abc123def456..."
|
|
settings:
|
|
type: object
|
|
description: Type-specific settings
|
|
properties:
|
|
admin_password:
|
|
type: string
|
|
minLength: 4
|
|
description: Admin password (room_server only)
|
|
example: "admin123"
|
|
guest_password:
|
|
type: string
|
|
minLength: 4
|
|
description: Guest password (room_server only)
|
|
example: "guest123"
|
|
max_posts:
|
|
type: integer
|
|
minimum: 1
|
|
maximum: 32
|
|
default: 32
|
|
description: Maximum messages to keep (room_server only, hard limit 32)
|
|
example: 32
|
|
|
|
ACLClient:
|
|
type: object
|
|
required: [public_key, public_key_full, address, permissions]
|
|
properties:
|
|
public_key:
|
|
type: string
|
|
description: Truncated public key for display (first 24 and last 8 chars)
|
|
example: "03ccf3bb0bed9a51...21416fff"
|
|
public_key_full:
|
|
type: string
|
|
pattern: '^[0-9a-fA-F]{64}$'
|
|
description: Full client public key (64 hex chars)
|
|
example: "03ccf3bb0bed9a5109868a1e33ed020519aab6dbb30e42df3b11a21d21416fff"
|
|
address:
|
|
type: string
|
|
description: Client address identifier
|
|
example: "e1"
|
|
permissions:
|
|
type: string
|
|
enum: [admin, guest, read_only]
|
|
description: |
|
|
Client permission level:
|
|
- admin: Full access
|
|
- guest: Limited access
|
|
- read_only: Read-only access
|
|
example: "admin"
|
|
last_activity:
|
|
type: integer
|
|
description: Unix timestamp of last activity
|
|
example: 1766065148
|
|
last_login_success:
|
|
type: integer
|
|
description: Unix timestamp of last successful login
|
|
example: 1766065146
|
|
last_timestamp:
|
|
type: integer
|
|
description: Unix timestamp from last client message
|
|
example: 1766065146
|
|
identity_name:
|
|
type: string
|
|
description: Name of the identity this client is authenticated to
|
|
example: "rrrrr"
|
|
identity_type:
|
|
type: string
|
|
enum: [repeater, room_server]
|
|
description: Type of identity
|
|
example: "room_server"
|
|
identity_hash:
|
|
type: string
|
|
pattern: '^0x[0-9a-fA-F]{2}$'
|
|
description: Hash of the identity
|
|
example: "0xC5"
|
|
|
|
securitySchemes:
|
|
BearerAuth:
|
|
type: http
|
|
scheme: bearer
|
|
bearerFormat: JWT
|
|
description: JWT token authentication via Authorization header
|
|
ApiKeyAuth:
|
|
type: apiKey
|
|
in: header
|
|
name: X-API-Key
|
|
description: API key authentication for machine-to-machine access
|
|
|
|
# Future security - currently open
|
|
# security:
|
|
# - ApiKeyAuth: []
|