Appearance
Device Management
Overview
The Device APIs operate in two scopes (see the Field Reference for identifier definitions):
- Organization-wide device list at
/api/v2/devices/, used to read every device under the active organization regardless of project. - Project-scoped device management at
/api/v2/projects/{project_id}/devices/, used for CRUD actions, data ingestion, and control commands for devices bound to a given project.
Devices are provisioned by hardware manufacturing flows and can only join an organization via the bind endpoint. Ad-hoc creation is not supported.
Endpoint Summary
| Scope | Method | Path | Purpose | Notes |
|---|---|---|---|---|
| Organization | GET | /api/v2/devices/ | List all devices visible to the current token | See Organization-wide Device List. |
| Project | GET | /api/v2/projects/{project_id}/devices/ | List devices inside a project, supports search/filter | See List Devices in Project. |
| Project | GET | /api/v2/projects/{project_id}/devices/{device_pk}/ | Retrieve device details | See Get Device Details. |
| Project | PUT/PATCH | /api/v2/projects/{project_id}/devices/{device_pk}/ | Update metadata (info, allow, project) | See Update Device. |
| Project | POST | /api/v2/projects/{project_id}/devices/bind/ | Bind an existing device (by device_id + safe_code) to the project | See Bind Device. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/unbind/ | Remove project binding | See Unbind Device. |
| Project | GET/POST | /api/v2/projects/{project_id}/devices/{device_pk}/data/ | Read cached telemetry or push uplink payloads | See Device Data Endpoints. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/reboot/ | Send reboot command (if supported) | See Device Control. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/set-serial/ | Configure serial parameters | See Device Control. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/set-tcp/ | Configure remote TCP endpoint | See Device Control. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/export-factors/ | Download factor configuration JSON | See Export/Import Factors. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/import-factors/ | Upload factor configuration JSON | See Export/Import Factors. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/add-module/ | Import factor templates from a module | See Add Module. |
| Project | POST | /api/v2/projects/{project_id}/devices/{device_pk}/set-project/ | Move device to another project within the same org | See Move Device to Another Project. |
Organization-wide Device List
Request
http
GET /api/v2/devices/
Authorization: Bearer <token>| Query | Type | Description |
|---|---|---|
search | string | Filter by device_id, device_name, or info (case-insensitive) |
project_id | string | Restrict results to a specific project |
Response
Returns a flat list (no pagination) of devices including device_id, device_name, info, allow, bind_time, create_time, and project reference.
Project-scoped Operations
All endpoints below use the base path /api/v2/projects/{project_id}/devices/. Replace {project_id} with the public project identifier and {device_pk} with the internal device primary key.
List Devices in Project
http
GET /api/v2/projects/{project_id}/devices/
Authorization: Bearer <token>Supports search query parameter identical to the organization endpoint. Responses are paginated (default page size depends on DRF settings) and cacheable for 60 seconds.
Get Device Details
http
GET /api/v2/projects/{project_id}/devices/{device_pk}/
Authorization: Bearer <token>Returns the payload including derived fields:
json
{
"id": 42,
"device_id": "868686000123456",
"device_name": "Cold-room node #1",
"info": "Walk-in freezer",
"allow": true,
"bind_time": "2024-01-08T10:00:00Z",
"has_thresholds": true,
"project": {
"project_id": "cold-chain-east",
"name": "Cold Chain East"
}
}Update Device Metadata
http
PATCH /api/v2/projects/{project_id}/devices/{device_pk}/
Authorization: Bearer <token>
Content-Type: application/json
{
"info": "Greenhouse #3 gateway",
"allow": true
}| Field | Type | Notes |
|---|---|---|
info | string | Updates operator-facing description |
allow | boolean | When false, the device cannot relay data |
project | PK | Only via set-project action; direct update is blocked |
Bind Device
Devices ship with a safe_code. Bind by referencing the hardware device_id and matching safe_code.
http
POST /api/v2/projects/{project_id}/devices/bind/
Authorization: Bearer <token>
Content-Type: application/json
{
"device_id": "868686000123456",
"safe_code": "8K2P"
}Successful responses return the newly bound device record. Errors:
| Status | Message |
|---|---|
| 404 | Device not found or safe code mismatch |
| 400 | Device already bound to another project |
| 404 | Project not found (invalid project_id) |
Unbind Device
http
POST /api/v2/projects/{project_id}/devices/{device_pk}/unbind/
Authorization: Bearer <token>Returns 204 No Content. After unbinding, the device becomes unassigned and can be bound to a different project.
Telemetry Endpoint
/data/ is dual-purpose:
- GET: fetches cached data for the device and its sub-devices. Response is an array of simple objects such as
{ "agri_id": "d-1000-abcd-01", "temp": 24.1, "t": 1708070400 }. Data is cached for ~120 seconds. - POST: accepts a list of data points from device gateways. The API enriches each item with
the_type,project_id,org_id, ensures timestamps exist, and pushes the payload into the SQS ingestion pipeline. Payload example:
json
[
{ "agri_id": "d-1000-abcd-01", "value": 24.3, "t": 1708070400 },
{ "agri_id": "d-1000-abcd-02", "value": 68.2 }
]Control & Configuration Actions
| Action | Path | Body | Notes |
|---|---|---|---|
| Reboot | POST /reboot/ | {} | Requires device online and SUPPORTS_REBOOT flag |
| Set Serial | POST /set-serial/ | { "baud_rate": 9600, "data_bits": 8, "stop_bits": 1, "parity": "NONE" } | Validates parameters, then emits NAT@AT+UART1 command followed by reboot |
| Set TCP | POST /set-tcp/ | { "host": "iot.yanjiiot.com", "port": 1883 } | Sends NAT@AT+SOCK1A command |
| Export Factors | POST /export-factors/ | null | Returns downloadable JSON with factor definitions |
| Import Factors | POST /import-factors/ | multipart form with file | Accepts exported JSON; optional clear_existing flag |
| Add Module | POST /add-module/ | { "module_id": 5, "slave_id": 1 } | Loads module templates into factors |
| Set Project | POST /set-project/ | { "project_id": "new-project" } | Moves device to another project within same organization |
Each action returns either a status message or the serialized device. Failures provide standard error envelopes.
Example: List Devices via Python
python
import requests
API_BASE = "https://dl.holdingbyte.com/api/v2"
TOKEN = "your_access_token"
def list_project_devices(project_id, search=None):
headers = {"Authorization": f"Bearer {TOKEN}"}
params = {"search": search} if search else None
url = f"{API_BASE}/projects/{project_id}/devices/"
response = requests.get(url, headers=headers, params=params)
response.raise_for_status()
return response.json()
devices = list_project_devices("greenhouse-alpha", search="gateway")
print(devices)Error Codes
| Status | Code | Description |
|---|---|---|
| 401 | UNAUTHORIZED | Missing or invalid token |
| 403 | FORBIDDEN | Caller lacks manager role or token not scoped to project |
| 404 | DEVICE_NOT_FOUND | Device PK not in project or project does not exist |
| 409 | DEVICE_ALREADY_BOUND | Bind attempted on already assigned device |
| 422 | INVALID_COMMAND | Control parameters fail validation |
| 500 | DEVICE_COMMAND_FAILED | Downstream failure while issuing command |
Operational Notes
- Caching: GET list/detail responses are cached. Use POST actions to invalidate state or wait for TTL (60–300 seconds).
- Data Integrity: When POSTing telemetry, ensure
agri_idvalues start with the parent deviceagri_idprefix; mismatches are dropped silently. - Safe Codes: Each hardware unit has a four-character safe code printed on the label. Share it securely; anyone with
device_id+safe_codecan bind the device. - Online Checks: Control actions verify device connectivity via
connect_timeand may return503 Service Unavailableif the device is offline. - Project Move:
set-projectrequires both projects to belong to the same organization. Moving a device clears cached listings for affected projects.
