Files
pyMC_Repeater/repeater/web/openapi.yaml
agessaman 2e25467c5d feat: enhance companion identity management and API documentation
- Added functionality to heal companion registration names with empty values.
- Improved handling of identity keys and public key derivation for companions.
- Updated API endpoints to support companion identity lookups using name, lookup_identity_key, or public_key_prefix.
- Enhanced OpenAPI documentation to clarify requirements for identity creation, updates, and deletions, including trimming whitespace from names.
2026-03-21 17:24:14 -07:00

2512 lines
76 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: 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"
/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
/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'
/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:
get:
tags: [Adverts]
summary: Get specific advert
description: Retrieve details of a specific advertisement
parameters:
- name: advert_id
in: query
required: true
schema:
type: integer
description: Advert ID to retrieve
responses:
'200':
description: Advert details
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
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
# ============================================================================
/global_flood_policy:
get:
tags: [Network Policy]
summary: Get global flood policy
description: Retrieve current network flood policy configuration
security:
- BearerAuth: []
- ApiKeyAuth: []
responses:
'200':
description: Current policy
content:
application/json:
schema:
type: object
post:
tags: [Network Policy]
summary: Update global 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
properties:
node_id:
type: string
description: Target node identifier
responses:
'200':
description: Ping sent
content:
application/json:
schema:
$ref: '#/components/schemas/SuccessResponse'
# ============================================================================
# Identity Management
# ============================================================================
/create_identity:
post:
tags: [Identities]
summary: Create new identity
description: |
Create a new repeater 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}$'
description: 32-byte hex key (64 chars). Omit for auto-generation
example: "abc123def456..."
type:
type: string
enum: [repeater, room_server]
description: |
- repeater: Repeater identity (only one allowed)
- 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
examples:
room_server:
value:
name: "General Chat"
type: room_server
settings:
admin_password: "admin123"
guest_password: "guest123"
max_posts: 32
repeater:
value:
name: "My Repeater"
type: repeater
identity_key: "abc123def456..."
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
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: []