REST & Authentication API Gateway¶
The API Gateway (api/) is a high-performance FastAPI service responsible for user authentication, channel management, device provisioning, API key issuance, and telemetry queries.
Technical Highlights¶
- Framework: FastAPI with Python 3.12+ and
uvicorn. - Database Driver:
asyncpgwith a pooled connection manager (api/database.py). - Security:
- User Passwords: Argon2id (via
pwdlib[argon2]). - Hardware / Session Credentials: Bcrypt (cost 10) for compatibility with
mosquitto-go-auth. - Tokens: Signed JWTs (HS256) with 15-minute access expiration and 30-day refresh tokens.
- HTTP API Keys: Cryptographic SHA-256 hash storage.
- Direct MQTT Forwarding: An internal persistent MQTT client (
api/mqtt_client.py) forwards HTTP data writes directly into the broker so live WebSocket and MQTT subscribers receive immediate events.
Router Modules¶
| Router | Path Prefix | Description |
|---|---|---|
auth |
/auth |
User registration, login (JWT generation), token refresh, and user profile. |
channels |
/channels |
Channel CRUD, field listings, and public/private channel access control. |
devices |
/channels/{id}/devices |
Hardware device provisioning, credentials rotation, and listing. |
keys |
/channels/{id}/keys |
Write / Read API key generation and revocation. |
mqtt |
/mqtt |
Short-lived (24h) MQTT session generation for frontend clients (POST /mqtt/session). |
data |
/channels/{id}/data |
Telemetry query with auto-downsampling and HTTP ingestion (POST). |
Dynamic Telemetry Query & Auto-Downsampling¶
When querying telemetry (GET /channels/{id}/data), the API dynamically selects the optimal storage representation based on the requested time window:
# api/routers/data.py
if resolution == "auto":
delta = end_time - start_time
if delta > timedelta(days=14):
target_resolution = "1h" # Query telemetry.points_1h
elif delta > timedelta(hours=6):
target_resolution = "1m" # Query telemetry.points_1m
else:
target_resolution = "raw" # Query telemetry.points
Response Schema¶
{
"channel_id": 42,
"start": "2026-11-12T00:00:00Z",
"end": "2026-11-12T12:00:00Z",
"resolution": "1m",
"fields": {
"1": "temperature",
"2": "humidity"
},
"points": [
{
"time": "2026-11-12T00:00:00Z",
"field": "temperature",
"field_id": 1,
"value": 23.4,
"min": 22.8,
"max": 24.1,
"count": 60
}
]
}
HTTP Ingestion Endpoint (Dual-Ingress)¶
Devices or external webhook services can publish via simple HTTP:
POST /channels/42/data
Host: api.example.com
X-API-Key: tl_write_xxxxxxxxxxxxxxxxxxxx
Content-Type: application/json
{
"temperature": 25.4,
"humidity": 60.2,
"status": "normal"
}
- The API validates the
X-API-Keyagainstapp.api_keyswherescope = 'write'. - It publishes the payload directly to the internal MQTT broker on topic
channels/42/data. - Mosquitto fans the message out to the Python Ingestion Bridge (for DB persistence) and all active Flutter/Web subscribers simultaneously.