# 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 ``` 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 - `2`: pending - `3`: lost - `4`: disabled --- ## 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" } ``` --- ## 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 (payload `device.status_id` is ignored) --- ### Device Check (State Polling) The server periodically publishes device check requests to the main MQTT topic and expects devices to respond on the same topic. **Topic**: `{configured_mqtt_topic}` **Request Message Published**: ```json { "type": "device_check_request", "device_id": "uuid", "requested_at": "2026-01-14T10:00:00Z" } ``` **Expected Device Response**: ```json { "type": "device_check_response", "device_id": "uuid", "status": "ok" | "lost" | "pending" } ``` --- ### Sensor Readings via MQTT Devices can publish sensor readings directly to the main MQTT topic. The server stores readings only if the `sensor_id` exists in the database. **Topic**: `{configured_mqtt_topic}` **Message Format**: ```json { "type": "sensor_reading", "sensor_id": "uuid", "value": 23.7, "value_at": "2026-01-14T10:00:00Z" } ``` **Notes**: - `type` may also be `sensor_value`. - `value` may be a number, boolean, or numeric string (e.g., "1", "0", "23.7"). - `value_at` is optional; if omitted, the server uses the current time. --- ## 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 | Pending | Device is initializing or awaiting | | 3 | Lost | Device has not checked in recently | | 4 | Disabled | Device is administratively disabled | ### Date/Time Format All timestamps use RFC3339 format: `2026-01-14T10:00:00Z` ### UUIDs UUIDs follow the standard UUID format (any version), e.g. `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 --- ## 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*