# Devices

## List all devices in a project

> Retrieves all devices in the specified project sorted by last\_seen (most recent first). Supports filtering by custom metadata fields to query specific device subsets.\
> \
> \*\*Metadata Filtering:\*\*\
> Filter devices by custom metadata fields using the format \`key:value,key2:value2\`\
> \
> Example: \`metadata=location:warehouse,floor:2\` returns devices where metadata.location="warehouse" AND metadata.floor="2"\
> \
> \*\*Response Fields:\*\*\
> \- Device credentials (MQTT username/password or HTTP token) are excluded in list view\
> \- Use GET /devices/{device\_id} to retrieve credentials for a specific device

```json
{"openapi":"3.0.0","info":{"title":"Qubitro Public API","version":"2.0"},"servers":[{"url":"https://api.qubitro.com"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Enter your API key with the Bearer prefix, e.g. \"Bearer QB_your_api_key_here\"","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"device.deviceItem":{"type":"object","properties":{"avatar":{"description":"Device avatar/icon URL","type":"string"},"brand":{"description":"Device brand (defaults to \"Custom\")","type":"string"},"description":{"description":"Device description (required, max 500 characters)","type":"string"},"device_credentials":{"description":"MQTT credentials (username, password) or HTTP token","type":"object","additionalProperties":{}},"id":{"description":"Unique device identifier","type":"string"},"last_seen":{"description":"Last time device sent data (ISO 8601 format, UTC)","type":"string"},"metadata":{"description":"Custom metadata key-value pairs for filtering and organization (e.g. location, floor, zone)","type":"object","additionalProperties":{}},"model":{"description":"Device model (defaults to \"Custom\")","type":"string"},"name":{"description":"Device name (required, max 100 characters)","type":"string"},"source":{"description":"Connection protocol: \"mqtt\", \"http\", or \"intemo-wifi\" (required for creation)","type":"string"},"tags":{"description":"Optional tags for categorization (alphanumeric and underscore only)","type":"array","items":{"type":"string"}}}}}},"paths":{"/v2/projects/{project_id}/devices":{"get":{"description":"Retrieves all devices in the specified project sorted by last_seen (most recent first). Supports filtering by custom metadata fields to query specific device subsets.\n\n**Metadata Filtering:**\nFilter devices by custom metadata fields using the format `key:value,key2:value2`\n\nExample: `metadata=location:warehouse,floor:2` returns devices where metadata.location=\"warehouse\" AND metadata.floor=\"2\"\n\n**Response Fields:**\n- Device credentials (MQTT username/password or HTTP token) are excluded in list view\n- Use GET /devices/{device_id} to retrieve credentials for a specific device","tags":["Devices"],"summary":"List all devices in a project","parameters":[{"description":"Project ID (UUID format)","name":"project_id","in":"path","required":true,"schema":{"type":"string"}},{"description":"Filter by metadata (format: key:value,key2:value2)","name":"metadata","in":"query","schema":{"type":"string"}}],"responses":{"200":{"description":"Devices retrieved successfully - Sorted by last_seen descending","content":{"application/json":{"schema":{"type":"array","items":{"$ref":"#/components/schemas/device.deviceItem"}}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Project not found or access denied","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Create a new device

> Creates a new device in the specified project and generates connection credentials automatically. The response includes MQTT credentials or HTTP token based on the selected protocol.\
> \
> \*\*Required Fields:\*\*\
> \- name: Device name (max 100 characters)\
> \- description: Device description (max 500 characters)\
> \- source: Connection protocol - "mqtt", "http", or "intemo-wifi"\
> \
> \*\*Optional Fields:\*\*\
> \- brand: Device brand (defaults to "Custom")\
> \- model: Device model (defaults to "Custom")\
> \- tags: Array of alphanumeric tags (e.g., \["sensor", "warehouse", "zone\_a"])\
> \- metadata: Custom key-value pairs for filtering (e.g., {"location": "warehouse", "floor": "2"})\
> \
> \*\*Generated Credentials:\*\*\
> \- MQTT: Returns username and password for broker connection\
> \- HTTP: Returns token for API authentication\
> \- Save credentials immediately - they cannot be retrieved again

```json
{"openapi":"3.0.0","info":{"title":"Qubitro Public API","version":"2.0"},"servers":[{"url":"https://api.qubitro.com"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Enter your API key with the Bearer prefix, e.g. \"Bearer QB_your_api_key_here\"","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"device.deviceItem":{"type":"object","properties":{"avatar":{"description":"Device avatar/icon URL","type":"string"},"brand":{"description":"Device brand (defaults to \"Custom\")","type":"string"},"description":{"description":"Device description (required, max 500 characters)","type":"string"},"device_credentials":{"description":"MQTT credentials (username, password) or HTTP token","type":"object","additionalProperties":{}},"id":{"description":"Unique device identifier","type":"string"},"last_seen":{"description":"Last time device sent data (ISO 8601 format, UTC)","type":"string"},"metadata":{"description":"Custom metadata key-value pairs for filtering and organization (e.g. location, floor, zone)","type":"object","additionalProperties":{}},"model":{"description":"Device model (defaults to \"Custom\")","type":"string"},"name":{"description":"Device name (required, max 100 characters)","type":"string"},"source":{"description":"Connection protocol: \"mqtt\", \"http\", or \"intemo-wifi\" (required for creation)","type":"string"},"tags":{"description":"Optional tags for categorization (alphanumeric and underscore only)","type":"array","items":{"type":"string"}}}}}},"paths":{"/v2/projects/{project_id}/devices":{"post":{"description":"Creates a new device in the specified project and generates connection credentials automatically. The response includes MQTT credentials or HTTP token based on the selected protocol.\n\n**Required Fields:**\n- name: Device name (max 100 characters)\n- description: Device description (max 500 characters)\n- source: Connection protocol - \"mqtt\", \"http\", or \"intemo-wifi\"\n\n**Optional Fields:**\n- brand: Device brand (defaults to \"Custom\")\n- model: Device model (defaults to \"Custom\")\n- tags: Array of alphanumeric tags (e.g., [\"sensor\", \"warehouse\", \"zone_a\"])\n- metadata: Custom key-value pairs for filtering (e.g., {\"location\": \"warehouse\", \"floor\": \"2\"})\n\n**Generated Credentials:**\n- MQTT: Returns username and password for broker connection\n- HTTP: Returns token for API authentication\n- Save credentials immediately - they cannot be retrieved again","tags":["Devices"],"summary":"Create a new device","parameters":[{"description":"Project ID (UUID format)","name":"project_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/device.deviceItem"}}},"description":"Device details","required":true},"responses":{"200":{"description":"Device created successfully - Includes generated connection credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/device.deviceItem"}}}},"400":{"description":"Invalid request body - Check required fields and format","content":{"application/json":{"schema":{"type":"object"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Project not found","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Get device details

> Retrieves detailed information about a specific device including connection credentials. Use this endpoint to get MQTT credentials or HTTP tokens required for device communication.\
> \
> \*\*Returned Credentials:\*\*\
> \- MQTT devices: Returns \`device\_credentials\` with \`username\` and \`password\`\
> \- HTTP devices: Returns \`device\_credentials\` with \`token\`\
> \
> \*\*Security Note:\*\*\
> Device credentials are sensitive. Store them securely on your device and never expose them publicly.

```json
{"openapi":"3.0.0","info":{"title":"Qubitro Public API","version":"2.0"},"servers":[{"url":"https://api.qubitro.com"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Enter your API key with the Bearer prefix, e.g. \"Bearer QB_your_api_key_here\"","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"device.deviceItem":{"type":"object","properties":{"avatar":{"description":"Device avatar/icon URL","type":"string"},"brand":{"description":"Device brand (defaults to \"Custom\")","type":"string"},"description":{"description":"Device description (required, max 500 characters)","type":"string"},"device_credentials":{"description":"MQTT credentials (username, password) or HTTP token","type":"object","additionalProperties":{}},"id":{"description":"Unique device identifier","type":"string"},"last_seen":{"description":"Last time device sent data (ISO 8601 format, UTC)","type":"string"},"metadata":{"description":"Custom metadata key-value pairs for filtering and organization (e.g. location, floor, zone)","type":"object","additionalProperties":{}},"model":{"description":"Device model (defaults to \"Custom\")","type":"string"},"name":{"description":"Device name (required, max 100 characters)","type":"string"},"source":{"description":"Connection protocol: \"mqtt\", \"http\", or \"intemo-wifi\" (required for creation)","type":"string"},"tags":{"description":"Optional tags for categorization (alphanumeric and underscore only)","type":"array","items":{"type":"string"}}}}}},"paths":{"/v2/projects/{project_id}/devices/{device_id}":{"get":{"description":"Retrieves detailed information about a specific device including connection credentials. Use this endpoint to get MQTT credentials or HTTP tokens required for device communication.\n\n**Returned Credentials:**\n- MQTT devices: Returns `device_credentials` with `username` and `password`\n- HTTP devices: Returns `device_credentials` with `token`\n\n**Security Note:**\nDevice credentials are sensitive. Store them securely on your device and never expose them publicly.","tags":["Devices"],"summary":"Get device details","parameters":[{"description":"Project ID (UUID format)","name":"project_id","in":"path","required":true,"schema":{"type":"string"}},{"description":"Device ID","name":"device_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Device retrieved successfully - Includes connection credentials","content":{"application/json":{"schema":{"$ref":"#/components/schemas/device.deviceItem"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"type":"object"}}}},"404":{"description":"Device not found or access denied","content":{"application/json":{"schema":{"type":"object"}}}}}}}}}
```

## Update a device

> Updates an existing device's properties. All fields are optional - only provided fields will be updated.\
> \
> \*\*Updatable Fields:\*\*\
> \- name: Device name (max 100 characters)\
> \- description: Device description (max 500 characters)\
> \- brand: Device brand\
> \- model: Device model\
> \- tags: Array of alphanumeric tags (replaces existing tags, minimum 1 required if provided)\
> \- metadata: Custom key-value pairs (replaces existing metadata, can be cleared with {})\
> \
> \*\*Non-Updatable Fields:\*\*\
> \- source: Connection protocol cannot be changed after creation\
> \- device\_credentials: Generated at creation, cannot be modified\
> \
> \*\*Partial Updates:\*\*\
> Only include fields you want to change. Omitted fields remain unchanged.\
> To clear metadata, pass an empty object {}.\
> Note: Tags cannot be cleared - at least one tag is required when updating tags.\
> \
> \*\*Example Request:\*\*\
> \`\`\`json\
> {\
> "name": "Updated Sensor Name",\
> "tags": \["production", "floor\_2"],\
> "metadata": {"location": "warehouse\_b", "zone": "cold\_storage"}\
> }\
> \`\`\`

````json
{"openapi":"3.0.0","info":{"title":"Qubitro Public API","version":"2.0"},"servers":[{"url":"https://api.qubitro.com"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Enter your API key with the Bearer prefix, e.g. \"Bearer QB_your_api_key_here\"","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"device.updateRequestBody":{"type":"object","properties":{"brand":{"description":"New device brand","type":"string"},"description":{"description":"New device description (max 500 characters)","type":"string"},"metadata":{"description":"New custom metadata (replaces existing metadata)","type":"object","additionalProperties":{}},"model":{"description":"New device model","type":"string"},"name":{"description":"New device name (max 100 characters)","type":"string"},"tags":{"description":"New tags (replaces existing, minimum 1 required)","type":"array","items":{"type":"string"}}}},"device.deviceItem":{"type":"object","properties":{"avatar":{"description":"Device avatar/icon URL","type":"string"},"brand":{"description":"Device brand (defaults to \"Custom\")","type":"string"},"description":{"description":"Device description (required, max 500 characters)","type":"string"},"device_credentials":{"description":"MQTT credentials (username, password) or HTTP token","type":"object","additionalProperties":{}},"id":{"description":"Unique device identifier","type":"string"},"last_seen":{"description":"Last time device sent data (ISO 8601 format, UTC)","type":"string"},"metadata":{"description":"Custom metadata key-value pairs for filtering and organization (e.g. location, floor, zone)","type":"object","additionalProperties":{}},"model":{"description":"Device model (defaults to \"Custom\")","type":"string"},"name":{"description":"Device name (required, max 100 characters)","type":"string"},"source":{"description":"Connection protocol: \"mqtt\", \"http\", or \"intemo-wifi\" (required for creation)","type":"string"},"tags":{"description":"Optional tags for categorization (alphanumeric and underscore only)","type":"array","items":{"type":"string"}}}},"main.ErrorResponse":{"type":"object","properties":{"action":{"description":"Action that was attempted","type":"string"},"code":{"description":"Optional error code","type":"string"},"details":{"description":"Optional additional details","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"success":{"description":"Operation failed","type":"boolean"}}}}},"paths":{"/v2/projects/{project_id}/devices/{device_id}":{"put":{"description":"Updates an existing device's properties. All fields are optional - only provided fields will be updated.\n\n**Updatable Fields:**\n- name: Device name (max 100 characters)\n- description: Device description (max 500 characters)\n- brand: Device brand\n- model: Device model\n- tags: Array of alphanumeric tags (replaces existing tags, minimum 1 required if provided)\n- metadata: Custom key-value pairs (replaces existing metadata, can be cleared with {})\n\n**Non-Updatable Fields:**\n- source: Connection protocol cannot be changed after creation\n- device_credentials: Generated at creation, cannot be modified\n\n**Partial Updates:**\nOnly include fields you want to change. Omitted fields remain unchanged.\nTo clear metadata, pass an empty object {}.\nNote: Tags cannot be cleared - at least one tag is required when updating tags.\n\n**Example Request:**\n```json\n{\n\"name\": \"Updated Sensor Name\",\n\"tags\": [\"production\", \"floor_2\"],\n\"metadata\": {\"location\": \"warehouse_b\", \"zone\": \"cold_storage\"}\n}\n```","tags":["Devices"],"summary":"Update a device","parameters":[{"description":"Project ID (UUID format)","name":"project_id","in":"path","required":true,"schema":{"type":"string"}},{"description":"Device ID","name":"device_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/device.updateRequestBody"}}},"description":"Fields to update","required":true},"responses":{"200":{"description":"Device updated successfully","content":{"application/json":{"schema":{"$ref":"#/components/schemas/device.deviceItem"}}}},"400":{"description":"Invalid request body - At least one field required","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"403":{"description":"Forbidden - API key missing 'update' scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"404":{"description":"Device not found or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}}}}}}}
````

## Delete a device

> \*\*⚠️ WARNING:\*\* Permanently deletes a device and ALL associated resources. This action CANNOT be undone.\
> \
> \*\*What Gets Deleted:\*\*\
> \- Device configuration and metadata\
> \- Device credentials (MQTT username/password or HTTP token)\
> \- \*\*All time-series data\*\* from TimescaleDB\
> \- \*\*All functions:\*\* decoder, transform, rules, storage functions, schedules\
> \- Storage views associated with the device\
> \- Widget references in dashboards\
> \- Dashboard associations\
> \
> \*\*What Happens:\*\*\
> 1\. Device stops receiving/sending data immediately\
> 2\. All historical data is permanently deleted\
> 3\. Functions stop executing\
> 4\. Dashboards using this device will show "device not found"\
> \
> \*\*Cannot Be Undone:\*\* There is no way to recover a deleted device or its data.\
> \
> \*\*Alternative:\*\* Use Data PURGE endpoint to delete only data while keeping device configuration\
> \
> \*\*Success Response:\*\*\
> \`\`\`json\
> {\
> "success": true,\
> "message": "Device deleted successfully",\
> "action": "delete device"\
> }\
> \`\`\`

````json
{"openapi":"3.0.0","info":{"title":"Qubitro Public API","version":"2.0"},"servers":[{"url":"https://api.qubitro.com"}],"security":[{"BearerAuth":[]}],"components":{"securitySchemes":{"BearerAuth":{"description":"Enter your API key with the Bearer prefix, e.g. \"Bearer QB_your_api_key_here\"","type":"apiKey","name":"Authorization","in":"header"}},"schemas":{"main.SuccessResponse":{"type":"object","properties":{"action":{"description":"Action that was performed","type":"string"},"message":{"description":"Human-readable success message","type":"string"},"success":{"description":"Operation completed successfully","type":"boolean"}}},"main.ErrorResponse":{"type":"object","properties":{"action":{"description":"Action that was attempted","type":"string"},"code":{"description":"Optional error code","type":"string"},"details":{"description":"Optional additional details","type":"string"},"message":{"description":"Human-readable error message","type":"string"},"success":{"description":"Operation failed","type":"boolean"}}}}},"paths":{"/v2/projects/{project_id}/devices/{device_id}":{"delete":{"description":"**⚠️ WARNING:** Permanently deletes a device and ALL associated resources. This action CANNOT be undone.\n\n**What Gets Deleted:**\n- Device configuration and metadata\n- Device credentials (MQTT username/password or HTTP token)\n- **All time-series data** from TimescaleDB\n- **All functions:** decoder, transform, rules, storage functions, schedules\n- Storage views associated with the device\n- Widget references in dashboards\n- Dashboard associations\n\n**What Happens:**\n1. Device stops receiving/sending data immediately\n2. All historical data is permanently deleted\n3. Functions stop executing\n4. Dashboards using this device will show \"device not found\"\n\n**Cannot Be Undone:** There is no way to recover a deleted device or its data.\n\n**Alternative:** Use Data PURGE endpoint to delete only data while keeping device configuration\n\n**Success Response:**\n```json\n{\n\"success\": true,\n\"message\": \"Device deleted successfully\",\n\"action\": \"delete device\"\n}\n```","tags":["Devices"],"summary":"Delete a device","parameters":[{"description":"Project ID (UUID format)","name":"project_id","in":"path","required":true,"schema":{"type":"string"}},{"description":"Device ID","name":"device_id","in":"path","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Device deleted successfully - All associated resources removed","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.SuccessResponse"}}}},"401":{"description":"Unauthorized - Invalid or missing API key","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"403":{"description":"Forbidden - Insufficient permissions (requires delete scope)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"404":{"description":"Device not found or access denied","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}}}}}}}
````


---

# Agent Instructions: Querying This Documentation

If you need additional information that is not directly available in this page, you can query the documentation dynamically by asking a question.

Perform an HTTP GET request on the current page URL with the `ask` query parameter:

```
GET https://docs.qubitro.com/developers/devices.md?ask=<question>
```

The question should be specific, self-contained, and written in natural language.
The response will contain a direct answer to the question and relevant excerpts and sources from the documentation.

Use this mechanism when the answer is not explicitly present in the current page, you need clarification or additional context, or you want to retrieve related documentation sections.
