# 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"}}}}}}}}}
```
