# Device Communication

## Download device file

> \*\*⚠️ ENTERPRISE FEATURE:\*\* Device Communication capabilities, including sending commands and managing firmware/logo files, are exclusive to Enterprise plans and require manual activation by the Qubitro team. This feature is not available by default and must be explicitly enabled for your organization.\
> \
> \*\*To enable this feature:\*\* Contact Qubitro support at <support@qubitro.com> or reach out to your account manager to discuss Enterprise plan options and feature activation.\
> \
> \---\
> \
> \*\*Device-only endpoint:\*\* Downloads a file (firmware or logo) using a time-limited download key. This endpoint is called by devices after receiving a \`download\_firmware\` or \`download\_logo\` command.\
> \
> \*\*How It Works:\*\*\
> 1\. User sends \`download\_firmware\` or \`download\_logo\` command to device (via \`/communication/command\` endpoint)\
> 2\. System generates a time-limited download key (30-minute expiry)\
> 3\. Device receives MQTT message with download URL: \`<https://api.qubitro.com/v2/device/download?key=xxx\\`\\>
> 4\. Device calls this endpoint with the key to download the file\
> 5\. Key is validated and file is served (key expires after use or 30 minutes)\
> \
> \*\*Authentication:\*\*\
> This endpoint requires \*\*device authentication\*\* (not user API key):\
> \- Header: \`Authorization: Basic {device\_token}\`\
> \- Device token is the device's MQTT password / HTTP token\
> \- Query parameter: \`key\` (download key received in command message)\
> \
> \*\*Security:\*\*\
> \- Download key is \*\*one-time use\*\* or expires after 30 minutes (whichever comes first)\
> \- Key is tied to a specific device ID (cannot be used by other devices)\
> \- Device token validation ensures only the intended device can download\
> \- File is temporarily cached and deleted after download\
> \
> \*\*Supported File Types:\*\*\
> \
> \| Type | Extensions | Use Case |\
> \|------|-----------|----------|\
> \| \*\*Firmware\*\* | \`.bin\`, \`.hex\`, \`.elf\` | OTA firmware updates |\
> \| \*\*Logo\*\* | \`.png\`, \`.jpg\`, \`.bmp\` | Device display images (e-ink, LCD) |\
> \
> \*\*Response:\*\*\
> \- Content-Type: \`application/octet-stream\`\
> \- Content-Disposition: \`attachment; filename={file\_name}\`\
> \- Content-Length: File size in bytes\
> \- Binary file data\
> \
> \*\*Timeout:\*\*\
> 15-minute timeout to support slow/cellular devices with large firmware files.\
> \
> \*\*Note:\*\* This endpoint is designed for device-to-server communication, not for users. Users should download files via the Qubitro web portal or use the \`/files\` endpoint to list available files.

```json
{"openapi":"3.0.0","info":{"title":"Qubitro Public API","version":"2.0"},"servers":[{"url":"https://api.qubitro.com"}],"security":[{"BasicAuth":[]}],"components":{"securitySchemes":{},"schemas":{"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/device/download":{"get":{"description":"**⚠️ ENTERPRISE FEATURE:** Device Communication capabilities, including sending commands and managing firmware/logo files, are exclusive to Enterprise plans and require manual activation by the Qubitro team. This feature is not available by default and must be explicitly enabled for your organization.\n\n**To enable this feature:** Contact Qubitro support at support@qubitro.com or reach out to your account manager to discuss Enterprise plan options and feature activation.\n\n---\n\n**Device-only endpoint:** Downloads a file (firmware or logo) using a time-limited download key. This endpoint is called by devices after receiving a `download_firmware` or `download_logo` command.\n\n**How It Works:**\n1. User sends `download_firmware` or `download_logo` command to device (via `/communication/command` endpoint)\n2. System generates a time-limited download key (30-minute expiry)\n3. Device receives MQTT message with download URL: `https://api.qubitro.com/v2/device/download?key=xxx`\n4. Device calls this endpoint with the key to download the file\n5. Key is validated and file is served (key expires after use or 30 minutes)\n\n**Authentication:**\nThis endpoint requires **device authentication** (not user API key):\n- Header: `Authorization: Basic {device_token}`\n- Device token is the device's MQTT password / HTTP token\n- Query parameter: `key` (download key received in command message)\n\n**Security:**\n- Download key is **one-time use** or expires after 30 minutes (whichever comes first)\n- Key is tied to a specific device ID (cannot be used by other devices)\n- Device token validation ensures only the intended device can download\n- File is temporarily cached and deleted after download\n\n**Supported File Types:**\n\n| Type | Extensions | Use Case |\n|------|-----------|----------|\n| **Firmware** | `.bin`, `.hex`, `.elf` | OTA firmware updates |\n| **Logo** | `.png`, `.jpg`, `.bmp` | Device display images (e-ink, LCD) |\n\n**Response:**\n- Content-Type: `application/octet-stream`\n- Content-Disposition: `attachment; filename={file_name}`\n- Content-Length: File size in bytes\n- Binary file data\n\n**Timeout:**\n15-minute timeout to support slow/cellular devices with large firmware files.\n\n**Note:** This endpoint is designed for device-to-server communication, not for users. Users should download files via the Qubitro web portal or use the `/files` endpoint to list available files.","tags":["Device Communication"],"summary":"Download device file","parameters":[{"description":"Time-limited download key (received in MQTT command message)","name":"key","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"File downloaded successfully - Binary data with Content-Disposition header","content":{"application/octet-stream":{"schema":{"type":"string","format":"binary"}}}},"401":{"description":"Unauthorized - Invalid or missing device token, or expired/invalid download key","content":{"application/octet-stream":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"403":{"description":"Forbidden - Download key does not match device ID (attempting to download another device's file)","content":{"application/octet-stream":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"404":{"description":"File not found - File may have been deleted or moved","content":{"application/octet-stream":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}}}}}}}
```

## Send command to device

> \*\*⚠️ ENTERPRISE FEATURE:\*\* Device Communication capabilities, including sending commands and managing firmware/logo files, are exclusive to Enterprise plans and require manual activation by the Qubitro team. This feature is not available by default and must be explicitly enabled for your organization.\
> \
> \*\*To enable this feature:\*\* Contact Qubitro support at <support@qubitro.com> or reach out to your account manager to discuss Enterprise plan options and feature activation.\
> \
> \---\
> \
> Sends a downlink command to a device via MQTT with QoS 2 (exactly-once delivery). Commands are delivered to the device control topic and can trigger configuration updates, firmware downloads, reboots, or custom actions.\
> \
> \*\*Supported Commands:\*\*\
> \
> \| Command | Purpose | Required Data Fields | Example |\
> \|---------|---------|---------------------|---------|\
> \| \`configuration\` | Send full configuration to device | Any config object | \`{"sampling\_rate": 60, "threshold": 30}\` |\
> \| \`send\_configuration\` | Request device to send current config | \`keys\`: array of config keys (optional) | \`{"keys": \["sampling\_rate", "threshold"]}\` |\
> \| \`download\_firmware\` | OTA firmware update | \`file\_name\`: firmware filename | \`{"file\_name": "firmware\_v2.1.0.bin"}\` |\
> \| \`download\_logo\` | Update device display logo | \`file\_name\`: logo filename | \`{"file\_name": "logo.png"}\` |\
> \| \`reboot\` | Reboot device | None (empty object) | \`{}\` |\
> \| \`reset\` | Factory reset device | None (empty object) | \`{}\` |\
> \| \*\*Custom\*\* | Device-specific commands | Device-defined | Varies by device |\
> \
> \*\*Command Delivery Protocol:\*\*\
> \- \*\*Protocol:\*\* MQTT with \*\*QoS 2\*\* (exactly-once delivery, no duplicates)\
> \- \*\*Topic:\*\* \`{device\_id}/control/{command}\` (e.g., \`dev-123/control/configuration\`)\
> \- \*\*Response Topic:\*\* \`{device\_id}/control/{command}/result\` (optional device acknowledgment)\
> \- \*\*Expiry:\*\* 30 minutes for download URLs (firmware/logo)\
> \- \*\*Retain:\*\* false (not stored on MQTT broker)\
> \
> \*\*Allowed Commands:\*\*\
> Devices can restrict which commands they accept via the \`allowed\_commands\` field in device metadata:\
> \- \*\*Empty list:\*\* All commands allowed (default)\
> \- \*\*Defined list:\*\* Only listed commands allowed (semicolon-separated: \`"configuration;reboot;reset"\`)\
> \- \*\*Unknown commands:\*\* Rejected with 403 Forbidden\
> \
> \*\*File Download Flow (firmware/logo):\*\*\
> 1\. Upload file to Qubitro storage (via Portal or API)\
> 2\. Send \`download\_firmware\` or \`download\_logo\` command with \`file\_name\`\
> 3\. System generates time-limited download key (30 min expiry)\
> 4\. MQTT message includes download URL: \`{"url": "<https://api.qubitro.com/v2/device/download?key=xxx>", "expires\_at": "2024-01-15T11:00:00Z"}\`\
> 5\. Device downloads file using provided URL and key\
> 6\. Key is validated and expires after 30 minutes or first use\
> \
> \*\*Prerequisites:\*\*\
> \- Device must support MQTT, Intemo WiFi, or Intemo Cellular (HTTP-only devices not supported)\
> \- For firmware/logo downloads: File must exist in project storage (upload via Portal first)\
> \- Must have \`send-commands\` scope permission\
> \
> \*\*Example Request - Configuration Update:\*\*\
> \`\`\`json\
> {\
> "command": "configuration",\
> "data": {\
> "sampling\_rate": 60,\
> "threshold\_high": 30,\
> "threshold\_low": 10,\
> "reporting\_interval": 300\
> }\
> }\
> \`\`\`\
> \
> \*\*Example Request - Firmware Update:\*\*\
> \`\`\`json\
> {\
> "command": "download\_firmware",\
> "data": {\
> "file\_name": "firmware\_v2.1.0.bin"\
> }\
> }\
> \`\`\`\
> \
> \*\*Success Response:\*\*\
> \`\`\`json\
> {\
> "success": true,\
> "message": "Command sent successfully",\
> "action": "send command"\
> }\
> \`\`\`

````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":{"devicecomm.sendCommandBody":{"type":"object","properties":{"command":{"description":"Command type: \"configuration\", \"send_configuration\", \"download_firmware\", \"download_logo\", \"reboot\", \"reset\", or custom commands","type":"string"},"data":{"description":"Command-specific data payload (JSON object)","type":"object","additionalProperties":{}}}},"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}/communication/command":{"post":{"description":"**⚠️ ENTERPRISE FEATURE:** Device Communication capabilities, including sending commands and managing firmware/logo files, are exclusive to Enterprise plans and require manual activation by the Qubitro team. This feature is not available by default and must be explicitly enabled for your organization.\n\n**To enable this feature:** Contact Qubitro support at support@qubitro.com or reach out to your account manager to discuss Enterprise plan options and feature activation.\n\n---\n\nSends a downlink command to a device via MQTT with QoS 2 (exactly-once delivery). Commands are delivered to the device control topic and can trigger configuration updates, firmware downloads, reboots, or custom actions.\n\n**Supported Commands:**\n\n| Command | Purpose | Required Data Fields | Example |\n|---------|---------|---------------------|---------|\n| `configuration` | Send full configuration to device | Any config object | `{\"sampling_rate\": 60, \"threshold\": 30}` |\n| `send_configuration` | Request device to send current config | `keys`: array of config keys (optional) | `{\"keys\": [\"sampling_rate\", \"threshold\"]}` |\n| `download_firmware` | OTA firmware update | `file_name`: firmware filename | `{\"file_name\": \"firmware_v2.1.0.bin\"}` |\n| `download_logo` | Update device display logo | `file_name`: logo filename | `{\"file_name\": \"logo.png\"}` |\n| `reboot` | Reboot device | None (empty object) | `{}` |\n| `reset` | Factory reset device | None (empty object) | `{}` |\n| **Custom** | Device-specific commands | Device-defined | Varies by device |\n\n**Command Delivery Protocol:**\n- **Protocol:** MQTT with **QoS 2** (exactly-once delivery, no duplicates)\n- **Topic:** `{device_id}/control/{command}` (e.g., `dev-123/control/configuration`)\n- **Response Topic:** `{device_id}/control/{command}/result` (optional device acknowledgment)\n- **Expiry:** 30 minutes for download URLs (firmware/logo)\n- **Retain:** false (not stored on MQTT broker)\n\n**Allowed Commands:**\nDevices can restrict which commands they accept via the `allowed_commands` field in device metadata:\n- **Empty list:** All commands allowed (default)\n- **Defined list:** Only listed commands allowed (semicolon-separated: `\"configuration;reboot;reset\"`)\n- **Unknown commands:** Rejected with 403 Forbidden\n\n**File Download Flow (firmware/logo):**\n1. Upload file to Qubitro storage (via Portal or API)\n2. Send `download_firmware` or `download_logo` command with `file_name`\n3. System generates time-limited download key (30 min expiry)\n4. MQTT message includes download URL: `{\"url\": \"https://api.qubitro.com/v2/device/download?key=xxx\", \"expires_at\": \"2024-01-15T11:00:00Z\"}`\n5. Device downloads file using provided URL and key\n6. Key is validated and expires after 30 minutes or first use\n\n**Prerequisites:**\n- Device must support MQTT, Intemo WiFi, or Intemo Cellular (HTTP-only devices not supported)\n- For firmware/logo downloads: File must exist in project storage (upload via Portal first)\n- Must have `send-commands` scope permission\n\n**Example Request - Configuration Update:**\n```json\n{\n\"command\": \"configuration\",\n\"data\": {\n\"sampling_rate\": 60,\n\"threshold_high\": 30,\n\"threshold_low\": 10,\n\"reporting_interval\": 300\n}\n}\n```\n\n**Example Request - Firmware Update:**\n```json\n{\n\"command\": \"download_firmware\",\n\"data\": {\n\"file_name\": \"firmware_v2.1.0.bin\"\n}\n}\n```\n\n**Success Response:**\n```json\n{\n\"success\": true,\n\"message\": \"Command sent successfully\",\n\"action\": \"send command\"\n}\n```","tags":["Device Communication"],"summary":"Send command to device","parameters":[{"description":"Project ID (UUID format)","name":"project_id","in":"path","required":true,"schema":{"type":"string"}},{"description":"Device ID (UUID format)","name":"device_id","in":"path","required":true,"schema":{"type":"string"}}],"requestBody":{"content":{"application/json":{"schema":{"$ref":"#/components/schemas/devicecomm.sendCommandBody"}}},"description":"Command and data payload - Structure varies by command type (see table above)","required":true},"responses":{"200":{"description":"Command sent successfully to MQTT broker - Device will receive via QoS 2","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.SuccessResponse"}}}},"400":{"description":"Invalid request body - Check command type and required data fields","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 - Command not in device's allowed_commands list or missing 'send-commands' scope","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}},"404":{"description":"Device not found or device does not support commands (HTTP-only devices)","content":{"application/json":{"schema":{"$ref":"#/components/schemas/main.ErrorResponse"}}}}}}}}}
````

## List device files

> \*\*⚠️ ENTERPRISE FEATURE:\*\* Device Communication capabilities, including sending commands and managing firmware/logo files, are exclusive to Enterprise plans and require manual activation by the Qubitro team. This feature is not available by default and must be explicitly enabled for your organization.\
> \
> \*\*To enable this feature:\*\* Contact Qubitro support at <support@qubitro.com> or reach out to your account manager to discuss Enterprise plan options and feature activation.\
> \
> \---\
> \
> Retrieves a list of all firmware or logo files uploaded for device communication (OTA updates, display images). Files can be filtered by project or listed organization-wide.\
> \
> \*\*What are Device Files?\*\*\
> Files stored in Qubitro for device communication purposes:\
> \- \*\*Firmware files:\*\* Binary files for OTA (Over-The-Air) firmware updates\
> \- \*\*Logo/image files:\*\* Images for device displays (e-ink, LCD screens)\
> \
> \*\*Supported File Types:\*\*\
> \
> \| Type | Extensions | Use Case | Upload Method |\
> \|------|-----------|----------|---------------|\
> \| \*\*firmware\*\* | \`.bin\`, \`.hex\`, \`.elf\` | OTA firmware updates | Qubitro Portal → Project → Files |\
> \| \*\*logo\*\* | \`.png\`, \`.jpg\`, \`.bmp\` | Device display images | Qubitro Portal → Project → Files |\
> \
> \*\*Query Parameter:\*\*\
> \- \`type\`: \*\*Required\*\* - Filter by file type (\`"firmware"\` or \`"logo"\`)\
> \
> \*\*Alternative Route:\*\*\
> This endpoint is also available at \`/v2/files?type={type}\` for listing files across all projects in your organization (without project\_id filter).\
> \
> \*\*File Information Returned:\*\*\
> \- \`name\` - File name (e.g., \`firmware\_v2.1.0.bin\`)\
> \- \`description\` - Optional description set during upload\
> \- \`time\` - Upload timestamp (ISO 8601 format, UTC)\
> \- \`size\` - File size in bytes\
> \
> \*\*Use Cases:\*\*\
> \- \*\*List available firmware\*\* before sending OTA update command\
> \- \*\*Verify file upload\*\* after uploading via Portal\
> \- \*\*Audit file inventory\*\* across projects\
> \- \*\*API integration\*\* to programmatically manage device files\
> \
> \*\*Sending Files to Devices:\*\*\
> After listing files, use the \`SendCommand\` endpoint with:\
> \- Command: \`download\_firmware\` (for firmware files)\
> \- Command: \`download\_logo\` (for logo files)\
> \- Data: \`{"file\_name": "{name from this list}"}\`\
> \
> \*\*Note:\*\* Files must be uploaded via the Qubitro web portal first. This API only lists existing files (upload via API not yet supported).

```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":{"devicecomm.getBlobListResponseBody":{"type":"object","properties":{"files":{"description":"Array of file objects","type":"array","items":{"$ref":"#/components/schemas/devicecomm.BlobObject"}}}},"devicecomm.BlobObject":{"type":"object","properties":{"description":{"description":"File description","type":"string"},"name":{"description":"File name","type":"string"},"size":{"description":"File size in bytes","type":"integer"},"time":{"description":"Upload timestamp (ISO 8601 format, UTC)","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}/files":{"get":{"description":"**⚠️ ENTERPRISE FEATURE:** Device Communication capabilities, including sending commands and managing firmware/logo files, are exclusive to Enterprise plans and require manual activation by the Qubitro team. This feature is not available by default and must be explicitly enabled for your organization.\n\n**To enable this feature:** Contact Qubitro support at support@qubitro.com or reach out to your account manager to discuss Enterprise plan options and feature activation.\n\n---\n\nRetrieves a list of all firmware or logo files uploaded for device communication (OTA updates, display images). Files can be filtered by project or listed organization-wide.\n\n**What are Device Files?**\nFiles stored in Qubitro for device communication purposes:\n- **Firmware files:** Binary files for OTA (Over-The-Air) firmware updates\n- **Logo/image files:** Images for device displays (e-ink, LCD screens)\n\n**Supported File Types:**\n\n| Type | Extensions | Use Case | Upload Method |\n|------|-----------|----------|---------------|\n| **firmware** | `.bin`, `.hex`, `.elf` | OTA firmware updates | Qubitro Portal → Project → Files |\n| **logo** | `.png`, `.jpg`, `.bmp` | Device display images | Qubitro Portal → Project → Files |\n\n**Query Parameter:**\n- `type`: **Required** - Filter by file type (`\"firmware\"` or `\"logo\"`)\n\n**Alternative Route:**\nThis endpoint is also available at `/v2/files?type={type}` for listing files across all projects in your organization (without project_id filter).\n\n**File Information Returned:**\n- `name` - File name (e.g., `firmware_v2.1.0.bin`)\n- `description` - Optional description set during upload\n- `time` - Upload timestamp (ISO 8601 format, UTC)\n- `size` - File size in bytes\n\n**Use Cases:**\n- **List available firmware** before sending OTA update command\n- **Verify file upload** after uploading via Portal\n- **Audit file inventory** across projects\n- **API integration** to programmatically manage device files\n\n**Sending Files to Devices:**\nAfter listing files, use the `SendCommand` endpoint with:\n- Command: `download_firmware` (for firmware files)\n- Command: `download_logo` (for logo files)\n- Data: `{\"file_name\": \"{name from this list}\"}`\n\n**Note:** Files must be uploaded via the Qubitro web portal first. This API only lists existing files (upload via API not yet supported).","tags":["Device Communication"],"summary":"List device files","parameters":[{"description":"Project ID (UUID format) - Filters files to this project only","name":"project_id","in":"path","required":true,"schema":{"type":"string"}},{"description":"File type filter: 'firmware' or 'logo'","name":"type","in":"query","required":true,"schema":{"type":"string"}}],"responses":{"200":{"description":"Array of file objects with name, description, size, and upload time","content":{"application/json":{"schema":{"$ref":"#/components/schemas/devicecomm.getBlobListResponseBody"}}}},"400":{"description":"Invalid parameters - type must be 'firmware' or 'logo'","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"}}}}}}}}}
```


---

# 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/device-communication.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.
