Skip to main content

Devices

Manage IoT devices.

List Devices

none
GET /devices
List devices. Users must provide hardware_ids, admins can list all.

Query Parameters

hardware_ids
string
List of hardware IDs. Repeated (?hardware_ids=id1&hardware_ids=id2) or comma-separated (?hardware_ids=id1%2Cid2%2Cid3). Required for users, optional for admins.
# User (filtered) – repeated or comma-separated
curl -H "X-API-Key: your-key" \
  "https://api.example.com/devices?hardware_ids=ABC123&hardware_ids=DEF456"
curl -H "X-API-Key: your-key" \
  "https://api.example.com/devices?hardware_ids=12317192%2C10631020%2C4564720"

# Admin (all devices)
curl -H "X-API-Key: your-admin-key" https://api.example.com/devices
[
  {
    "_id": "...",
    "device_id": "a1b2c3d4",
    "hardware_id": "ABC123",
    "device_type": "iotee_device",
    "name": "Scooter #1",
    "attributes": {
      "lat": 37.7749,
      "long": -122.4194,
      "battery_voltage": 12.4,
      "lock_status": 0
    },
    "is_online": true,
    "created_at": "2025-12-01T00:00:00.000Z",
    "updated_at": "2025-12-17T10:30:00.000Z"
  }
]

Get Device

none
GET /devices/:id
Get a single device by device_id or hardware_id.
curl -H "X-API-Key: your-key" https://api.example.com/devices/ABC123
{
  "_id": "...",
  "device_id": "a1b2c3d4",
  "hardware_id": "ABC123",
  "device_type": "iotee_device",
  "name": "Scooter #1",
  "attributes": {},
  "is_online": true,
  "created_at": "2025-12-01T00:00:00.000Z",
  "updated_at": "2025-12-17T10:30:00.000Z"
}

Get Device with Details

none
GET /devices/:id/details
Get device with telemetry counts. Admin only 🔐
curl -H "X-API-Key: your-admin-key" https://api.example.com/devices/ABC123/details
{
  "_id": "...",
  "device_id": "a1b2c3d4",
  "hardware_id": "ABC123",
  "device_type": "iotee_device",
  "name": "Scooter #1",
  "attributes": {},
  "is_online": true,
  "created_at": "2025-12-01T00:00:00.000Z",
  "updated_at": "2025-12-17T10:30:00.000Z",
  "telemetry_counts": {
    "gps": 3500,
    "battery": 1200
  }
}

Update Device Name

none
PATCH /devices/:id
Update device name. Set to null to clear.

Request Body

name
string | null
required
New device name, or null to clear
curl -X PATCH https://api.example.com/devices/ABC123 \
  -H "X-API-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"name": "New Device Name"}'
{
  "success": true
}

Full Device Update

none
PUT /devices/:id
Full device update. Admin only 🔐

Request Body

name
string
Device name
device_type
string
Device type identifier
attributes
object
Custom attributes
curl -X PUT https://api.example.com/devices/ABC123 \
  -H "X-API-Key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{"name": "Updated Name", "device_type": "new_type", "attributes": {"custom": "value"}}'

Delete Device

none
DELETE /devices/:id
Delete a device. Admin only 🔐
curl -X DELETE -H "X-API-Key: your-admin-key" \
  https://api.example.com/devices/a1b2c3d4
{
  "success": true,
  "deleted": "a1b2c3d4"
}

Bulk Delete Devices

none
POST /devices/bulk-delete
Delete multiple devices. Admin only 🔐

Request Body

device_ids
string[]
required
Array of device IDs to delete
curl -X POST https://api.example.com/devices/bulk-delete \
  -H "X-API-Key: your-admin-key" \
  -H "Content-Type: application/json" \
  -d '{"device_ids": ["a1b2c3d4", "e5f6g7h8"]}'
{
  "success": true,
  "deleted": 2
}

Device Config

Device config is the single declaration of a device’s active capabilities and operational parameters. Config is validated against the device type’s config schema (JSON Schema) on every write.

Get Config

none
GET /devices/:id/config
Get the device’s current config. Add ?schema=true to include the device type’s config schema and defaults.

Query Parameters

schema
boolean
When true, includes the JSON Schema capability contract and default config for the device type.
# Config only
curl -H "X-API-Key: your-key" https://api.example.com/devices/ABC123/config

# Config + schema + defaults
curl -H "X-API-Key: your-key" "https://api.example.com/devices/ABC123/config?schema=true"
{
  "config": {
    "tracker_mode": 1,
    "wifi_enabled": 1,
    "keypad_enabled": 0,
    "ping_interval": 180
  },
  "schema": {
    "type": "object",
    "properties": {
      "tracker_mode": { "type": "number", "enum": [0, 1], "description": "Tracker mode (0=off, 1=on)", "default": 1 },
      "wifi_enabled": { "type": "number", "enum": [0, 1], "description": "WiFi enabled (0/1)", "default": 1 }
    },
    "additionalProperties": false
  },
  "defaults": {
    "tracker_mode": 1,
    "wifi_enabled": 1,
    "keypad_enabled": 0,
    "ping_interval": 180
  }
}

Replace Config

none
PUT /devices/:id/config
Replace the entire device config. The body is validated against the device type’s config schema. Invalid configs are rejected with 400 and structured error details.
curl -X PUT https://api.example.com/devices/ABC123/config \
  -H "X-API-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"tracker_mode": 1, "wifi_enabled": 0, "ping_interval": 60}'
{
  "config": {
    "tracker_mode": 1,
    "wifi_enabled": 0,
    "ping_interval": 60
  }
}

Patch Config

none
PATCH /devices/:id/config
Merge partial updates into the device config. The merged result is validated against the config schema before persisting.
curl -X PATCH https://api.example.com/devices/ABC123/config \
  -H "X-API-Key: your-key" \
  -H "Content-Type: application/json" \
  -d '{"wifi_enabled": 0}'
{
  "config": {
    "tracker_mode": 1,
    "wifi_enabled": 0,
    "ping_interval": 180
  }
}

Reset Config

none
DELETE /devices/:id/config
Reset the device config to the device type’s defaults.
curl -X DELETE -H "X-API-Key: your-key" \
  https://api.example.com/devices/ABC123/config
{
  "config": {
    "tracker_mode": 1,
    "wifi_enabled": 1,
    "keypad_enabled": 0,
    "ping_interval": 180
  }
}

Publish Config

none
POST /devices/:id/config/publish
Push the device’s saved config to the device over MQTT. Config save and config publish are separate operations — saving does not automatically push to the device.
curl -X POST -H "X-API-Key: your-key" \
  https://api.example.com/devices/ABC123/config/publish
{
  "success": true,
  "published": true,
  "messages": 4
}

Validation Errors

When a config write fails validation, the response includes structured error details:
{
  "error": "Config validation failed",
  "details": [
    { "path": "/tracker_mode", "message": "must be equal to one of the allowed values" },
    { "path": "/unknown_field", "message": "must NOT have additional properties" }
  ]
}

Capabilities

Device capabilities are derived from the device’s current config, not from telemetry. Each device type defines a config schema — the full superset of config options the type supports. A device instance’s active capabilities are the subset of that schema that is configured (enabled) in the device’s config. Capabilities are returned on device list and detail responses as a capabilities array of strings (e.g. ["gps", "lock", "battery", "wifi"]). The config schema can be fetched via GET /devices/:id/config?schema=true for client-driven form generation.

Lock & Key/Keyless Capabilities

CapabilityMeaning
lockDevice has lock hardware and accepts lock/unlock commands (used by system/geofence and, when allowed, by user)
key_keylessDevice supports key vs keyless mode switching (two-relay, BLE mode 1). UI should show a key/keyless toggle
UI rules:
  • Show the key/keyless toggle only when capabilities includes key_keyless.
  • Show the Lock/Unlock button only when key_keyless is present and config.key_keyless_state === "keyless".
  • Devices with lock but without key_keyless (e.g. BLE mode 2) have lock hardware for system/geofence use only — no manual Lock/Unlock in the UI.
Config field: key_keyless_state ("key" | "keyless" | "hybrid" | null)
  • "key" — Physical key only. User cannot lock/unlock remotely.
  • "keyless" — Remote lock/unlock only. No physical key.
  • "hybrid" — Physical key works and remote lock/unlock also allowed.
  • null — Not applicable (device does not support key/keyless switching, e.g. BLE mode 2 or no BLE).
Show Lock/Unlock in UI when key_keyless capability is present and key_keyless_state is "keyless" or "hybrid".