Files
lambdaiot-core/API.md

1025 lines
15 KiB
Markdown

# Lambda IoT Core API Documentation
## Overview
The Lambda IoT Core API provides a RESTful interface for managing IoT devices, sensors, actors, and sensor readings. The API uses JWT authentication for protected endpoints and integrates with MQTT for real-time device communication.
**Base URL**: `http://localhost:8080` (default)
## Authentication
Most endpoints require JWT authentication. Include the token in the `Authorization` header:
```
Authorization: Bearer <your-jwt-token>
```
Tokens are obtained through the `/login` endpoint and are valid for 24 hours.
---
## Public Endpoints
### Health Check
Check the service health status.
**Endpoint**: `GET /health`
**Authentication**: None required
**Response**:
```json
{
"status": "ok"
}
```
---
### Hello
Simple greeting endpoint for testing connectivity.
**Endpoint**: `GET /hello`
**Authentication**: None required
**Response**:
```json
{
"message": "hello from lambdaiot"
}
```
---
### Register
Create a new user account.
**Endpoint**: `POST /register`
**Authentication**: None required
**Request Body**:
```json
{
"username": "string (required, min: 3, max: 50)",
"password": "string (required, min: 6)",
"email": "string (optional)"
}
```
**Response** (201 Created):
```json
{
"id": "uuid",
"username": "string"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid request format
- `409 Conflict`: Username already exists
- `500 Internal Server Error`: Database or server error
---
### Login
Authenticate and receive a JWT token.
**Endpoint**: `POST /login`
**Authentication**: None required
**Request Body**:
```json
{
"username": "string",
"password": "string"
}
```
**Response** (200 OK):
```json
{
"token": "jwt-token-string"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid JSON
- `401 Unauthorized`: Invalid credentials
- `500 Internal Server Error`: Database or token generation error
---
### List All Devices
Retrieve all devices in the system (public read access).
**Endpoint**: `GET /devices`
**Authentication**: None required
**Response** (200 OK):
```json
[
{
"id": "uuid",
"name": "string",
"description": "string",
"location": "string",
"status_id": 1,
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:00Z"
}
]
```
**Status IDs**:
- `1`: OK/Online
- `2`: Warning
- `3`: Error
- `4`: Offline
---
## Protected Endpoints
All endpoints below require JWT authentication.
### Protected Test
Test authentication and view token claims.
**Endpoint**: `GET /protected`
**Authentication**: Required
**Response** (200 OK):
```json
{
"claims": {
"sub": "username",
"user_id": "uuid",
"exp": 1705324800
}
}
```
---
## Device Endpoints
### Create Device
Create a new device.
**Endpoint**: `POST /devices`
**Authentication**: Required
**Request Body**:
```json
{
"name": "string (required)",
"description": "string (required)",
"location": "string (required)",
"status_id": 1 (required, range: 1-4)
}
```
**Response** (201 Created):
```json
{
"id": "uuid"
}
```
---
### Get Device
Retrieve a specific device by ID.
**Endpoint**: `GET /devices/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Device UUID
**Response** (200 OK):
```json
{
"id": "uuid",
"name": "string",
"description": "string",
"location": "string",
"status_id": 1,
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:00Z"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid device ID
- `404 Not Found`: Device not found
---
### Update Device
Update an existing device.
**Endpoint**: `PUT /devices/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Device UUID
**Request Body** (all fields optional):
```json
{
"name": "string",
"description": "string",
"location": "string",
"status_id": 1
}
```
**Response** (200 OK):
```json
{
"message": "device updated"
}
```
---
### Delete Device
Delete a device.
**Endpoint**: `DELETE /devices/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Device UUID
**Response** (200 OK):
```json
{
"message": "device deleted"
}
```
---
## Sensor Endpoints
### Create Sensor
Create a new sensor for a device.
**Endpoint**: `POST /sensors`
**Authentication**: Required
**Request Body**:
```json
{
"device_id": "uuid (required)",
"name": "string (required)",
"type": "string (required)",
"data_type_id": 1 (required, min: 1)
}
```
**Response** (201 Created):
```json
{
"id": "uuid"
}
```
---
### List All Sensors
Retrieve all sensors.
**Endpoint**: `GET /sensors`
**Authentication**: Required
**Response** (200 OK):
```json
[
{
"id": "uuid",
"device_id": "uuid",
"name": "string",
"type": "string",
"data_type_id": 1,
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:00Z"
}
]
```
---
### Get Sensor
Retrieve a specific sensor by ID.
**Endpoint**: `GET /sensors/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Sensor UUID
**Response** (200 OK):
```json
{
"id": "uuid",
"device_id": "uuid",
"name": "string",
"type": "string",
"data_type_id": 1,
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:00Z"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid sensor ID
- `404 Not Found`: Sensor not found
---
### Update Sensor
Update an existing sensor.
**Endpoint**: `PUT /sensors/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Sensor UUID
**Request Body** (all fields optional):
```json
{
"device_id": "uuid",
"name": "string",
"type": "string",
"data_type_id": 1
}
```
**Response** (200 OK):
```json
{
"message": "sensor updated"
}
```
---
### Delete Sensor
Delete a sensor.
**Endpoint**: `DELETE /sensors/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Sensor UUID
**Response** (200 OK):
```json
{
"message": "sensor deleted"
}
```
---
### Trigger Sensor
Request a new reading from a sensor via MQTT.
**Endpoint**: `POST /sensors/:id/trigger`
**Authentication**: Required
**Path Parameters**:
- `id`: Sensor UUID
**Request Body** (optional):
```json
{
"action": "string (default: 'read')"
}
```
**Response** (202 Accepted):
```json
{
"status": "published",
"topic": "lambdaiot"
}
```
**MQTT Message Published**:
```json
{
"type": "sensor_trigger",
"sensor_id": "uuid",
"action": "read",
"requested_at": "2026-01-14T10:00:00Z"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid sensor ID
- `404 Not Found`: Sensor not found
- `500 Internal Server Error`: Failed to publish to MQTT
---
## Actor Endpoints
### Create Actor
Create a new actor for a device.
**Endpoint**: `POST /actors`
**Authentication**: Required
**Request Body**:
```json
{
"device_id": "uuid (required)",
"name": "string (required)",
"type": "string (required)",
"data_type_id": 1 (required, min: 1)
}
```
**Response** (201 Created):
```json
{
"id": "uuid"
}
```
---
### List All Actors
Retrieve all actors.
**Endpoint**: `GET /actors`
**Authentication**: Required
**Response** (200 OK):
```json
[
{
"id": "uuid",
"device_id": "uuid",
"name": "string",
"type": "string",
"data_type_id": 1,
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:00Z"
}
]
```
---
### Get Actor
Retrieve a specific actor by ID.
**Endpoint**: `GET /actors/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Actor UUID
**Response** (200 OK):
```json
{
"id": "uuid",
"device_id": "uuid",
"name": "string",
"type": "string",
"data_type_id": 1,
"created_at": "2026-01-14T10:00:00Z",
"updated_at": "2026-01-14T10:00:00Z"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid actor ID
- `404 Not Found`: Actor not found
---
### Update Actor
Update an existing actor.
**Endpoint**: `PUT /actors/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Actor UUID
**Request Body** (all fields optional):
```json
{
"device_id": "uuid",
"name": "string",
"type": "string",
"data_type_id": 1
}
```
**Response** (200 OK):
```json
{
"message": "actor updated"
}
```
---
### Delete Actor
Delete an actor.
**Endpoint**: `DELETE /actors/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Actor UUID
**Response** (200 OK):
```json
{
"message": "actor deleted"
}
```
---
### Write to Actor
Send a command to an actor via MQTT.
**Endpoint**: `POST /actors/:id/write`
**Authentication**: Required
**Path Parameters**:
- `id`: Actor UUID
**Request Body**:
```json
{
"action": "string (required)",
"value": "any JSON value (optional)"
}
```
**Response** (202 Accepted):
```json
{
"status": "published",
"topic": "lambdaiot"
}
```
**MQTT Message Published**:
```json
{
"type": "actor_command",
"actor_id": "uuid",
"action": "string",
"value": "any",
"requested_at": "2026-01-14T10:00:00Z"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid actor ID or missing action
- `404 Not Found`: Actor not found
- `500 Internal Server Error`: Failed to publish to MQTT
---
## Sensor Reading Endpoints
### Create Sensor Reading
Create a new sensor reading.
**Endpoint**: `POST /sensor-readings`
**Authentication**: Required
**Request Body**:
```json
{
"sensor_id": "uuid (required)",
"value": 123.45 (required),
"value_at": "2026-01-14T10:00:00Z (optional, defaults to now)"
}
```
**Response** (201 Created):
```json
{
"id": 123
}
```
---
### List Sensor Readings
Retrieve sensor readings with optional filtering and pagination.
**Endpoint**: `GET /sensor-readings`
**Authentication**: Required
**Query Parameters**:
- `sensor_id`: Filter by sensor UUID (optional)
- `limit`: Number of results (default: 100, max: 1000)
- `page`: Page number for pagination (default: 0)
**Response** (200 OK):
```json
[
{
"id": 123,
"sensor_id": "uuid",
"value": 123.45,
"value_at": "2026-01-14T10:00:00Z"
}
]
```
---
### Get Sensor Reading
Retrieve a specific sensor reading by ID.
**Endpoint**: `GET /sensor-readings/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Reading ID (integer)
**Response** (200 OK):
```json
{
"id": 123,
"sensor_id": "uuid",
"value": 123.45,
"value_at": "2026-01-14T10:00:00Z"
}
```
**Error Responses**:
- `400 Bad Request`: Invalid reading ID
- `404 Not Found`: Reading not found
---
### Update Sensor Reading
Update an existing sensor reading.
**Endpoint**: `PUT /sensor-readings/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Reading ID (integer)
**Request Body** (all fields optional):
```json
{
"value": 123.45,
"value_at": "2026-01-14T10:00:00Z"
}
```
**Response** (200 OK):
```json
{
"message": "sensor reading updated"
}
```
---
### Delete Sensor Reading
Delete a sensor reading.
**Endpoint**: `DELETE /sensor-readings/:id`
**Authentication**: Required
**Path Parameters**:
- `id`: Reading ID (integer)
**Response** (200 OK):
```json
{
"message": "sensor reading deleted"
}
```
---
## MQTT & System Endpoints
### MQTT Ping
Publish a ping message to the MQTT broker for testing.
**Endpoint**: `GET /mqttping`
**Authentication**: Required
**Response** (200 OK):
```json
{
"timestamp": "2026-01-14T10:00:00Z",
"topic": "lambdaiot"
}
```
**MQTT Message Published**:
```json
{
"type": "ping",
"timestamp": "2026-01-14T10:00:00Z"
}
```
---
### Get State Messages
Retrieve stored state messages from SQLite storage.
**Endpoint**: `GET /messages`
**Authentication**: Required
**Query Parameters**:
- `page`: Page number (default: 0)
**Response** (200 OK):
```json
{
"messages": [
{
"id": 1,
"payload": "message content",
"timestamp": "2026-01-14T10:00:00Z"
}
]
}
```
---
## MQTT Integration
### Device Discovery
Devices can announce themselves by publishing to the discovery topic:
**Topic**: `{configured_mqtt_topic}/discovery`
**Message Format**:
```json
{
"mac_address": "00:11:22:33:44:55",
"device": {
"id": "uuid",
"name": "Device Name",
"description": "Device Description",
"location": "Device Location",
"status_id": 1
},
"sensors": [
{
"id": "uuid",
"name": "Temperature Sensor",
"type": "temperature",
"data_type_id": 1
}
],
"actors": [
{
"id": "uuid",
"name": "LED Actuator",
"type": "led",
"data_type_id": 2
}
]
}
```
**Behavior**:
- New devices are automatically created with all sensors and actors
- Existing devices are updated, and sensors/actors are synced
- Device status is set to OK (1) upon discovery
---
## Error Responses
All endpoints may return the following standard error responses:
### 400 Bad Request
```json
{
"error": "descriptive error message"
}
```
### 401 Unauthorized
```json
{
"error": "invalid credentials" // or "no claims"
}
```
### 404 Not Found
```json
{
"error": "resource not found"
}
```
### 409 Conflict
```json
{
"error": "resource already exists"
}
```
### 500 Internal Server Error
```json
{
"error": "descriptive error message"
}
```
---
## Data Types
### Device Status IDs
| ID | Status | Description |
|----|---------|--------------------------------|
| 1 | OK | Device is online and functioning |
| 2 | Warning | Device has warnings |
| 3 | Error | Device has errors |
| 4 | Offline | Device is offline |
### Date/Time Format
All timestamps use RFC3339 format: `2026-01-14T10:00:00Z`
### UUIDs
UUIDs follow the standard UUID v4 format: `550e8400-e29b-41d4-a716-446655440000`
---
## Configuration
The server uses a configuration file (typically `config.toml`) with the following structure:
```toml
[server]
address = ":8080"
port = 8080
jwt_secret = "your-secret-key"
[database]
host = "localhost"
port = 3306
user = "root"
password = "password"
name = "lambdaiot"
[mqtt]
broker = "tcp://localhost:1883"
topic = "lambdaiot"
client_id = "lambdaiot-core"
username = ""
password = ""
```
---
## Rate Limiting & Best Practices
1. **Pagination**: Use `limit` and `page` parameters for large result sets
2. **MQTT Topics**: All MQTT messages are published to the configured topic
3. **Token Expiry**: JWT tokens expire after 24 hours - refresh as needed
4. **UUID Format**: Always use valid UUID v4 format for device, sensor, and actor IDs
5. **Date Format**: Use RFC3339 format for all timestamp fields
6. **Device Discovery**: Devices can self-register via MQTT discovery messages
7. **State Messages**: Messages on topics starting with `state:` are automatically stored
---
## Example Workflows
### Complete Device Setup Workflow
1. Register a user:
```bash
POST /register
{"username": "admin", "password": "secret123"}
```
2. Login and get token:
```bash
POST /login
{"username": "admin", "password": "secret123"}
```
3. Create a device:
```bash
POST /devices (with JWT)
{"name": "Room Sensor", "description": "Living room", "location": "Floor 1", "status_id": 1}
```
4. Create a sensor:
```bash
POST /sensors (with JWT)
{"device_id": "device-uuid", "name": "Temperature", "type": "temp", "data_type_id": 1}
```
5. Trigger a reading:
```bash
POST /sensors/{sensor-id}/trigger (with JWT)
{"action": "read"}
```
6. Create a reading:
```bash
POST /sensor-readings (with JWT)
{"sensor_id": "sensor-uuid", "value": 22.5}
```
### Query Readings for a Specific Sensor
```bash
GET /sensor-readings?sensor_id={uuid}&limit=50&page=0 (with JWT)
```
---
## Support & Documentation
For more information about device discovery specifications, see [DEVICE_DISCOVERY_SPEC.md](DEVICE_DISCOVERY_SPEC.md).
---
*Generated: January 14, 2026*