API Documentation - xante8088/kasa-monitor GitHub Wiki
API Documentation
Complete REST API reference for Kasa Monitor.
Base URL
http://localhost:5272/api
Authentication (Enhanced v1.2.0)
Most endpoints require JWT authentication with dual-token system (access + refresh tokens). The application uses secure JWT secret management with rotation support.
Login
POST /api/auth/login
Content-Type: application/json
{
"username": "admin",
"password": "password123"
}
Response:
{
"access_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc...",
"token_type": "bearer",
"expires_in": 1800,
"user": {
"id": 1,
"username": "admin",
"email": "[email protected]",
"role": "admin",
"permissions": ["all"]
},
"session": {
"session_id": "sess_abc123",
"created_at": "2024-01-01T10:00:00Z",
"expires_at": "2024-01-01T10:30:00Z"
}
}
Refresh Token (New v1.2.0)
POST /api/auth/refresh
Content-Type: application/json
{
"refresh_token": "eyJ0eXAiOiJKV1QiLCJhbGc..."
}
Response:
{
"access_token": "new_access_token",
"refresh_token": "new_refresh_token",
"token_type": "bearer",
"expires_in": 1800,
"user": {
"username": "admin",
"role": "admin"
}
}
Using Token
Include in Authorization header:
Authorization: Bearer eyJ0eXAiOiJKV1QiLCJhbGc...
Endpoints
Authentication
Check Setup Required
GET /api/auth/setup-required
Returns whether initial admin setup is needed.
Create Admin (First Time)
POST /api/auth/setup
Content-Type: application/json
{
"username": "admin",
"email": "[email protected]",
"password": "securepassword",
"full_name": "Admin User"
}
Get Current User
GET /api/auth/me
Authorization: Bearer {token}
Logout
POST /api/auth/logout
Authorization: Bearer {token}
Response:
{
"message": "Logged out successfully",
"sessions_terminated": 1
}
Get Active Sessions (New v1.2.0)
GET /api/auth/sessions
Authorization: Bearer {token}
Response:
{
"sessions": [
{
"session_id": "sess_abc123",
"ip_address": "192.168.1.100",
"user_agent": "Mozilla/5.0...",
"created_at": "2024-01-01T10:00:00Z",
"last_activity": "2024-01-01T10:25:00Z",
"expires_at": "2024-01-01T10:30:00Z",
"is_current": true
}
],
"total": 2,
"max_allowed": 3
}
Terminate Session (New v1.2.0)
DELETE /api/auth/sessions/{session_id}
Authorization: Bearer {token}
Security Status (New v1.2.0)
GET /api/auth/security-status
Authorization: Bearer {admin_token}
Response:
{
"jwt_configuration": {
"algorithm": "HS256",
"access_token_expire_minutes": 30,
"refresh_token_expire_days": 7
},
"security_features": {
"token_refresh_enabled": true,
"session_management_available": true,
"audit_logging_enabled": true,
"structured_error_responses": true
}
}
Error Responses (New v1.2.0)
All authentication errors now return structured JSON:
401 Unauthorized:
{
"error": "authentication_expired",
"message": "Your session has expired. Please log in again.",
"error_code": "TOKEN_EXPIRED",
"timestamp": "2024-01-01T10:00:00Z",
"redirect_to": "/login"
}
403 Forbidden:
{
"error": "authorization_failed",
"message": "You don't have permission to access this resource",
"error_code": "INSUFFICIENT_PERMISSIONS",
"required_permission": "ADMIN_ACCESS"
}
429 Rate Limited:
{
"error": "rate_limit_exceeded",
"message": "Too many requests. Please try again later.",
"retry_after": 60,
"limit": "10 per hour"
}
Device Management
List All Devices
GET /api/devices
Response:
[
{
"device_ip": "192.168.1.100",
"alias": "Living Room Lamp",
"model": "HS110",
"device_type": "plug",
"is_on": true,
"current_power_w": 45.2,
"today_energy_kwh": 0.361,
"month_energy_kwh": 10.45,
"voltage": 120.1,
"current": 0.38,
"signal_strength": -45,
"last_seen": "2024-01-15T10:30:00Z"
}
]
Discover Devices
POST /api/discover
Content-Type: application/json
{
"username": "[email protected]", // Optional
"password": "tplinkpassword" // Optional
}
Response:
{
"discovered": 5
}
Add Manual Device
POST /api/devices/manual
Content-Type: application/json
{
"ip": "192.168.1.100",
"alias": "Kitchen Plug" // Optional
}
Get Device Details
GET /api/device/{device_ip}
Get Device History (Enhanced v1.2.1)
GET /api/device/{device_ip}/history?period=7d&aggregation=auto&timezone=America/New_York
Query Parameters:
period: Predefined time period (24h, 7d, 30d, 3m, 6m, 1y) - v1.2.1start_time: ISO 8601 datetime (optional, for custom range)end_time: ISO 8601 datetime (optional, for custom range)interval: Data aggregation interval (5m, 1h, 6h, 1d, 1w) - deprecated, useaggregationaggregation: Data aggregation level (auto, raw, hourly, daily, weekly, monthly) - v1.2.1timezone: User's timezone for proper date alignment - v1.2.1
Automatic Aggregation (v1.2.1):
When using aggregation=auto, the system automatically determines optimal intervals:
- 24h → 5-minute intervals
- 7d → Hourly intervals
- 30d → 6-hour intervals
- 3m/6m → Daily intervals
- 1y → Weekly intervals
Response (v1.2.1):
{
"data": [
{
"timestamp": "2024-01-15T10:00:00Z",
"power_w": 45.2,
"energy_kwh": 0.045,
"cost": 0.005,
"min_power_w": 40.1,
"max_power_w": 50.3,
"avg_power_w": 45.2
}
],
"metadata": {
"count": 168,
"period": "7d",
"aggregation": "1h",
"cached": true,
"query_time_ms": 45
}
}
Get Device Statistics
GET /api/device/{device_ip}/stats
Response:
{
"daily_usage_kwh": 0.86,
"weekly_usage_kwh": 6.02,
"monthly_usage_kwh": 25.8,
"daily_cost": 0.10,
"weekly_cost": 0.72,
"monthly_cost": 3.09,
"average_power_w": 35.8,
"peak_power_w": 125.0,
"total_on_time_hours": 18.5
}
Control Device
POST /api/device/{device_ip}/control
Content-Type: application/json
{
"action": "on" // or "off", "toggle"
}
Remove Device
DELETE /api/devices/{device_ip}
Electricity Rates
Get Current Rates
GET /api/rates
Response:
{
"rate_type": "tiered",
"currency": "USD",
"rate_structure": {
"tier1_limit": 500,
"tier1_rate": 0.10,
"tier2_limit": 1000,
"tier2_rate": 0.12,
"tier3_rate": 0.15
},
"time_of_use_rates": [
{
"start_hour": 0,
"end_hour": 6,
"rate": 0.08,
"label": "Off-Peak"
},
{
"start_hour": 6,
"end_hour": 22,
"rate": 0.12,
"label": "Peak"
}
]
}
Update Rates
POST /api/rates
Content-Type: application/json
{
"rate_type": "simple",
"currency": "USD",
"rate_structure": {
"rate_per_kwh": 0.12
}
}
Cost Analysis
Calculate Costs
GET /api/costs?start_date=2024-01-01&end_date=2024-01-31
Response:
{
"total_cost": 45.67,
"total_kwh": 380.5,
"average_daily_cost": 1.47,
"devices": [
{
"device_ip": "192.168.1.100",
"device_name": "Living Room",
"total_kwh": 125.3,
"total_cost": 15.04,
"percentage": 32.9
}
],
"daily_breakdown": [
{
"date": "2024-01-15",
"kwh": 12.5,
"cost": 1.50
}
]
}
User Management
List Users
GET /api/users
Authorization: Bearer {admin_token}
Create User
POST /api/users
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"username": "john",
"email": "[email protected]",
"password": "password123",
"full_name": "John Doe",
"role": "viewer"
}
Update User
PATCH /api/users/{user_id}
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"role": "operator",
"is_active": true
}
Delete User
DELETE /api/users/{user_id}
Authorization: Bearer {admin_token}
Two-Factor Authentication
Check 2FA Status
GET /api/auth/2fa/status
Authorization: Bearer {token}
Response:
{
"enabled": false
}
Setup 2FA
POST /api/auth/2fa/setup
Authorization: Bearer {token}
Response:
{
"secret": "JBSWY3DPEHPK3PXP",
"qr_code": "data:image/png;base64,...",
"backup_codes": [
"ABC123",
"DEF456",
"GHI789"
]
}
Verify 2FA
POST /api/auth/2fa/verify
Authorization: Bearer {token}
Content-Type: application/json
{
"token": "123456"
}
Disable 2FA
POST /api/auth/2fa/disable
Authorization: Bearer {token}
System Configuration
Get System Config
GET /api/system/config
Authorization: Bearer {admin_token}
Update System Config
PUT /api/system/config
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"polling_interval": 60,
"data_retention_days": 365,
"allow_device_control": true,
"require_https": false
}
Get System Status
GET /api/system/status
Response:
{
"version": "1.0.0",
"uptime_seconds": 3600,
"devices_connected": 5,
"database_size_mb": 45.2,
"last_poll": "2024-01-15T10:30:00Z"
}
Network Settings
Get Network Configuration
GET /api/settings/network
Response:
{
"network_mode": "bridge",
"discovery_enabled": false,
"manual_devices_enabled": true,
"host_ip": "172.17.0.1"
}
Data Export (Enhanced Security v1.2.0)
Required Permission: DATA_EXPORT
Rate Limit: 10 exports per hour per user
Audit Logging: All operations logged for compliance
User Ownership: Users can only access their own exports (admin override available)
Get Export Formats
GET /api/exports/formats
Authorization: Bearer {token_with_data_export_permission}
Response:
{
"formats": [
{
"id": "csv",
"name": "CSV",
"description": "Comma-separated values",
"mime_type": "text/csv",
"extension": ".csv"
},
{
"id": "json",
"name": "JSON",
"description": "JavaScript Object Notation",
"mime_type": "application/json",
"extension": ".json"
},
{
"id": "excel",
"name": "Excel",
"description": "Microsoft Excel workbook",
"mime_type": "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet",
"extension": ".xlsx"
}
]
}
Get Available Devices for Export
GET /api/exports/devices
Authorization: Bearer {token_with_data_export_permission}
Response:
{
"devices": [
{
"device_ip": "192.168.1.100",
"device_name": "Living Room Lamp",
"device_type": "plug",
"last_seen": "2024-01-15T10:30:00Z",
"data_points": 8760
}
]
}
Get Available Metrics
GET /api/exports/metrics
Authorization: Bearer {token_with_data_export_permission}
Response:
{
"metrics": [
{
"field": "power_w",
"name": "Power (Watts)",
"description": "Instantaneous power consumption",
"data_type": "float",
"unit": "W"
},
{
"field": "energy_kwh",
"name": "Energy (kWh)",
"description": "Cumulative energy consumption",
"data_type": "float",
"unit": "kWh"
},
{
"field": "cost",
"name": "Cost",
"description": "Calculated energy cost",
"data_type": "float",
"unit": "currency"
}
]
}
Create Export
POST /api/exports/create
Authorization: Bearer {token_with_data_export_permission}
Content-Type: application/json
{
"export_type": "device_data",
"devices": ["192.168.1.100", "192.168.1.101"],
"date_range": {
"start": "2024-01-01T00:00:00Z",
"end": "2024-01-31T23:59:59Z"
},
"format": "csv",
"fields": ["timestamp", "power_w", "energy_kwh", "cost"],
"aggregation": "hourly",
"options": {
"include_headers": true,
"timezone": "America/New_York"
}
}
Response:
{
"export_id": "export_12345",
"status": "queued",
"created_at": "2024-01-15T10:30:00Z",
"user_id": 1,
"estimated_completion": "2024-01-15T10:32:00Z",
"download_url": "/api/exports/download/export_12345"
}
Get Export Status
GET /api/exports/{export_id}
Authorization: Bearer {token}
Response:
{
"export_id": "export_12345",
"status": "completed",
"progress": 100,
"created_at": "2024-01-15T10:30:00Z",
"completed_at": "2024-01-15T10:31:45Z",
"user_id": 1,
"file_size": 1024000,
"record_count": 744,
"download_url": "/api/exports/download/export_12345",
"expires_at": "2024-01-22T10:31:45Z"
}
Security Note: Users can only access their own exports unless they have admin role.
Get Export History
GET /api/exports/history?limit=50&offset=0
Authorization: Bearer {token}
Response:
{
"exports": [
{
"export_id": "export_12345",
"export_type": "device_data",
"format": "csv",
"status": "completed",
"created_at": "2024-01-15T10:30:00Z",
"user_id": 1,
"username": "admin",
"file_size": 1024000,
"record_count": 744,
"retention_days": 7,
"expires_at": "2024-01-22T10:30:00Z"
}
],
"total": 25,
"page": 1,
"per_page": 50
}
Security Note: Regular users only see their own exports.
Download Export
GET /api/exports/download/{export_id}
Authorization: Bearer {token}
Security: Validates user ownership before download.
Delete Export
DELETE /api/exports/{export_id}
Authorization: Bearer {token}
Response:
{
"message": "Export deleted successfully",
"export_id": "export_12345",
"deleted_at": "2024-01-15T11:00:00Z"
}
Security: Users can only delete their own exports.
Preview Export Data
GET /api/exports/preview?export_type=device_data&devices=192.168.1.100&limit=5
Authorization: Bearer {token_with_data_export_permission}
Response:
{
"preview": [
{
"timestamp": "2024-01-15T10:00:00Z",
"device_ip": "192.168.1.100",
"device_name": "Living Room Lamp",
"power_w": 45.2,
"energy_kwh": 0.045,
"cost": 0.005
}
],
"total_records": 8760,
"estimated_file_size": "2.1 MB"
}
Get Export Statistics
GET /api/exports/stats
Authorization: Bearer {token}
Response:
{
"total_exports": 156,
"exports_this_month": 23,
"total_data_exported": "450.2 MB",
"most_popular_format": "csv",
"user_exports_remaining": 7
}
Export Error Responses
Permission Denied (403):
{
"detail": "Permission denied",
"error_code": "PERMISSION_DENIED",
"message": "You don't have permission to perform data exports",
"required_permission": "DATA_EXPORT"
}
Access Denied - Ownership (403):
{
"detail": "Access denied to export",
"error_code": "ACCESS_DENIED",
"message": "You don't have access to this export",
"export_owner": "other_user"
}
Rate Limit Exceeded (429):
{
"detail": "Export rate limit exceeded",
"error_code": "RATE_LIMIT_EXCEEDED",
"message": "Export rate limit exceeded. Please try again later.",
"limit": "10 per hour",
"retry_after": "2024-01-15T11:30:00Z"
}
SSL Certificate Management (Enhanced v1.2.0)
New Features:
- Persistent storage across Docker restarts
- Automatic certificate detection and loading
- Database path storage for persistence
- Cross-device link error fixed
Get SSL Files
GET /api/ssl/files
Authorization: Bearer {admin_token}
Response:
{
"cert_exists": true,
"key_exists": true,
"cert_info": {
"subject": "CN=localhost",
"issuer": "CN=localhost",
"valid_from": "2024-01-01",
"valid_until": "2025-01-01"
}
}
Generate CSR
POST /api/ssl/generate-csr
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"common_name": "kasa-monitor.local",
"organization": "My Organization",
"country": "US",
"state": "CA",
"locality": "San Francisco"
}
Download SSL Files
GET /api/ssl/download/{filename}
Authorization: Bearer {admin_token}
Where filename can be:
cert.pem- SSL certificatekey.pem- Private keycsr.pem- Certificate signing request
Upload SSL Certificate
POST /api/system/ssl/upload-cert
Authorization: Bearer {admin_token}
Content-Type: multipart/form-data
Form Data:
file: (certificate file)
Security Notes:
- File size limited by MAX_UPLOAD_SIZE_MB (default: 10MB)
- File type validation enforced
- Files are quarantined and validated before processing
Upload SSL Private Key
POST /api/system/ssl/upload-key
Authorization: Bearer {admin_token}
Content-Type: multipart/form-data
Form Data:
file: (private key file)
Security Notes:
- File size limited by MAX_UPLOAD_SIZE_MB (default: 10MB)
- File type validation enforced
- Files are quarantined and validated before processing
Backup Management
List Backups
GET /api/backups
Authorization: Bearer {admin_token}
Response:
[
{
"filename": "kasa_backup_20240115_103000.7z",
"size": 1048576,
"created": "2024-01-15T10:30:00Z",
"type": "manual",
"includes": ["database", "config", "logs"]
}
]
Create Backup
POST /api/backups/create
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"type": "manual",
"include_logs": true,
"include_exports": false,
"compression": "high"
}
Download Backup
GET /api/backups/{filename}/download
Authorization: Bearer {admin_token}
Delete Backup
DELETE /api/backups/{filename}
Authorization: Bearer {admin_token}
Restore Backup
POST /api/backups/restore
Authorization: Bearer {admin_token}
Content-Type: multipart/form-data
Form Data:
file: (backup file)
options: {"restore_config": true, "restore_database": true}
Get Backup Progress
GET /api/backups/progress
Authorization: Bearer {admin_token}
Backup Schedules
Get Backup Schedules
GET /api/backups/schedules
Authorization: Bearer {admin_token}
Create Backup Schedule
POST /api/backups/schedules
Authorization: Bearer {admin_token}
Content-Type: application/json
{
"name": "Daily Backup",
"cron": "0 2 * * *",
"enabled": true,
"retention_days": 30,
"options": {
"include_logs": true,
"compression": "normal"
}
}
Update Backup Schedule
PUT /api/backups/schedules/{schedule_id}
Authorization: Bearer {admin_token}
Delete Backup Schedule
DELETE /api/backups/schedules/{schedule_id}
Authorization: Bearer {admin_token}
Health Monitoring
Basic Health Check
GET /api/health
Response:
{
"status": "healthy",
"timestamp": "2024-01-15T10:30:00Z"
}
Detailed Health Check
GET /api/health/detailed
Authorization: Bearer {admin_token}
Response:
{
"status": "healthy",
"components": {
"database": {
"status": "healthy",
"response_time_ms": 5,
"details": {
"size_mb": 45.2,
"device_count": 10,
"reading_count": 50000
}
},
"device_manager": {
"status": "healthy",
"connected_devices": 8,
"failed_devices": 2
},
"cache": {
"status": "healthy",
"hit_rate": 0.85,
"memory_usage_mb": 128
},
"scheduler": {
"status": "healthy",
"jobs_pending": 3,
"jobs_running": 1
}
},
"uptime_seconds": 86400,
"memory_usage_mb": 256,
"cpu_usage_percent": 15.5
}
WebSocket Events
Connect to WebSocket for real-time updates:
const socket = io('ws://localhost:5272');
socket.on('connect', () => {
console.log('Connected to WebSocket');
// Subscribe to device updates
socket.emit('subscribe_device', { device_ip: '192.168.1.100' });
});
socket.on('device_update', (data) => {
console.log('Device updated:', data);
});
Events
Device Update
{
"event": "device_update",
"device_ip": "192.168.1.100",
"data": {
"is_on": true,
"current_power_w": 45.2,
"timestamp": "2024-01-15T10:30:00Z"
}
}
Device Status Change
{
"event": "device_status",
"device_ip": "192.168.1.100",
"status": "online", // or "offline"
"timestamp": "2024-01-15T10:30:00Z"
}
Error Responses
Standard Error Format
{
"detail": "Error message",
"status_code": 400,
"error_code": "INVALID_REQUEST"
}
Common Status Codes
200- Success201- Created400- Bad Request401- Unauthorized403- Forbidden404- Not Found409- Conflict422- Validation Error500- Internal Server Error
Rate Limiting
API requests are limited to:
- 100 requests per minute per IP
- 1000 requests per hour per user
Headers indicate rate limit status:
X-RateLimit-Limit: 100
X-RateLimit-Remaining: 95
X-RateLimit-Reset: 1704456000
CORS Policy
Cross-Origin Resource Sharing (CORS) is strictly enforced:
- Origins must be explicitly whitelisted via CORS_ALLOWED_ORIGINS
- No wildcard origins allowed in production
- Preflight requests are validated
- CORS violations are logged for security monitoring
File Upload Security
All file uploads are subject to:
- Size limits (MAX_UPLOAD_SIZE_MB, default: 10MB)
- File type validation (extension and MIME type)
- Quarantine and validation before processing
- Plugin signature verification (when REQUIRE_PLUGIN_SIGNATURES=true)
Examples
Python
import requests
# Login
response = requests.post('http://localhost:5272/api/auth/login', json={
'username': 'admin',
'password': 'password123'
})
token = response.json()['access_token']
# Get devices
headers = {'Authorization': f'Bearer {token}'}
devices = requests.get('http://localhost:5272/api/devices', headers=headers)
print(devices.json())
JavaScript
// Login
const loginRes = await fetch('http://localhost:5272/api/auth/login', {
method: 'POST',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify({
username: 'admin',
password: 'password123'
})
});
const { access_token } = await loginRes.json();
// Get devices
const devicesRes = await fetch('http://localhost:5272/api/devices', {
headers: { 'Authorization': `Bearer ${access_token}` }
});
const devices = await devicesRes.json();
cURL
# Login
TOKEN=$(curl -s -X POST http://localhost:5272/api/auth/login \
-H "Content-Type: application/json" \
-d '{"username":"admin","password":"password123"}' \
| jq -r .access_token)
# Get devices
curl -H "Authorization: Bearer $TOKEN" \
http://localhost:5272/api/devices
SDK Support
While there's no official SDK yet, the API is designed to be simple and RESTful. Community SDKs are welcome!
API Versioning
The API uses URL versioning. Current version is v1 (implied in /api/).
Future versions will use /api/v2/ format.
Need Help?
Document Version: 2.1.0
Last Updated: 2025-08-27
Review Status: Current
Change Summary: Updated for v1.2.1 with enhanced history endpoint featuring time period support, automatic aggregation, and performance optimizations