Build on EdgeConductor
in minutes, not days
Official SDKs for JS and Python, a REST API, MQTT topics, and ESP32 libraries. Everything you need — no vendor lock-in, no bloat.
npm install @edgeconductor/sdk
const { EdgeConductor } = require('@edgeconductor/sdk');
const ec = new EdgeConductor({ apiKey: 'ec_live_xxxx' });
// 1. Register device (first time only)
await ec.devices.register({
serial_no: 'MY-DEVICE-001',
product_type: 'EC-CLIMATE-V1',
});
// 2. Push telemetry
await ec.telemetry.push('MY-DEVICE-001', {
temp: 24.5, hum: 60, co2: 850, bat: 4.1,
});
// 3. Read live shadow
const shadow = await ec.devices.getShadow('MY-DEVICE-001');
// → { temp: 24.5, hum: 60, co2: 850, bat: 4.1 }
// 4. Create threshold alert rule
await ec.rules.threshold(orgId, {
name: 'CO2 High Alert',
field: 'co2', op: '>', value: 1000,
action: { key: 'relay', value: true },
});CLI — ec
v0.1.0Manage devices, push OTA firmware, stream live telemetry, and provision factory batches — all from the terminal. Designed for CI/CD pipelines, factory floors, and engineers who prefer the command line.
Install
npm install -g @edgeconductor/cli
Authenticate
ec login # saves ~/.ec/config.json
ec login # save API key + registry URL → ~/.ec/config.json ec whoami # show current login ec logout # remove saved credentials
ec device list # list all devices ec device list --org <org_id> # filter by org ec device create EC-TRACK-001 tracker # register a device ec device get EC-TRACK-001 # device info + shadow state ec device shadow EC-TRACK-001 relay true # push to shadow_desired via MQTT ec device reboot EC-TRACK-001 # remote reboot ec device delete EC-TRACK-001 # delete (--force if active)
ec telemetry watch EC-TRACK-001 # stream live telemetry (every 5s) ec telemetry watch EC-TRACK-001 -i 10 # custom poll interval (seconds) ec telemetry get EC-TRACK-001 -n 20 # last 20 records ec telemetry get EC-TRACK-001 --hours 2 # last 2 hours
ec ota upload ./firmware.bin --version 2.1.4 --type tracker # → uploads binary, caches to ~/.ec/last_upload.json ec ota push --serial EC-TRACK-001 # push to one device ec ota push --type tracker # push to all trackers ec ota jobs # list recent OTA jobs ec ota job 12 # status + progress of job #12
ec manufacture 50 --prefix EC-TRACK --type tracker # → registers EC-TRACK-00001 to EC-TRACK-00050 # → manufacture_output/manufacture_EC-TRACK_<ts>.csv # → manufacture_output/qr_EC-TRACK_<ts>/EC-TRACK-00001.png (per device) ec manufacture 10 --prefix EC-TRACK --type tracker --start 100 # continue batch ec manufacture 20 --prefix EC-CLIM --type climate --claim-url https://portal.co/claim
ec org list ec org create "Acme Corp"
Authentication
Get an API Key
Login to the dashboard → Org Settings → API Keys → Generate Key. The key is shown only once — store it securely.
Open Dashboard →Bearer Token
Authorization: Bearer ec_live_xxxx
All authenticated endpoints require this header. Keys are scoped to your org — never expose them client-side.
SDK Reference
v0.2.0devices.register({ serial_no, product_type, fw_version? })→ Promise<Device>Register a new device. Safe to call repeatedly — idempotent.
devices.list({ orgId?, tenantId? })→ Promise<Device[]>List devices. Filter by org or tenant.
devices.get(serial)→ Promise<Device>Full device object including shadow_reported and shadow_desired.
devices.getShadow(serial)→ Promise<object>Shorthand for get() — returns only shadow_reported (latest sensor values).
devices.pushConfig(serial, config)→ Promise<object>Update desired state → delivered to device via MQTT.
devices.reboot(serial)→ Promise<object>Send reboot command to device via MQTT.
devices.assign(serial, { orgId?, roomId? })→ Promise<object>Assign device to an org and/or room.
telemetry.push(serial, payload)→ Promise<{ok}>Push telemetry. Keys: temp, hum, co2, bat, signal, lat, lng, speed — any numeric field accepted.
telemetry.history(serial, { hours, limit })→ Promise<[]>Historical records oldest-first. hours: 1 | 6 | 24 | 168.
telemetry.recent(serial, limit?)→ Promise<[]>Last N records newest-first. Default limit: 20.
telemetry.stream(serial, callback, { intervalMs })→ { stop() }Live stream — polls every intervalMs, calls callback only when payload changes. Returns stop handle.
rules.list(orgId)→ Promise<Rule[]>All rules for an org.
rules.threshold(orgId, { name, field, op, value, action, webhookUrl? })→ Promise<Rule>Create threshold rule. op: '>' | '<' | '>=' | '<=' | '==' | '!='.
rules.schedule(orgId, { name, time, days, action })→ Promise<Rule>Create schedule rule. time: 'HH:MM', days: ['mon','tue',...].
rules.enable(ruleId) / rules.disable(ruleId)→ Promise<Rule>Toggle rule on/off without deleting.
rules.delete(ruleId)→ Promise<object>Permanently delete rule.
orgs.list()→ Promise<Org[]>All organizations you have access to.
orgs.get(orgId)→ Promise<Org>Org details including white-label settings.
orgs.rooms(orgId)→ Promise<Room[]>All rooms/zones in org.
orgs.createRoom(orgId, { name, floor, building })→ Promise<Room>Create a new room.
audit.list(orgId, { limit? })→ Promise<Event[]>Last N audit events. Actions: rule_fired, device_offline, ota_pushed, config_pushed.
notifications.list(orgId)→ Promise<Notification[]>In-app notifications for an org — device offline, anomalies, firmware updates.
notifications.markRead(id)→ Promise<Notification>Mark a single notification as read.
notifications.markAllRead(orgId)→ Promise<object>Mark all notifications as read for the org.
anomalies.list(orgId, { limit?, unacked? })→ Promise<Anomaly[]>List anomaly events. Pass unacked: true to get only unacknowledged alerts.
anomalies.acknowledge(anomalyId)→ Promise<Anomaly>Acknowledge (dismiss) an anomaly event from the panel.
firmware.list()→ Promise<Release[]>List all firmware releases uploaded to the platform.
firmware.push(serial, firmwareId)→ Promise<object>Push a specific firmware release to a device. Device must be registered.
apiKeys.generate(orgId, name)→ Promise<{ key }>Generate a new API key. Raw key returned once — store it securely.
apiKeys.list(orgId)→ Promise<Key[]>List API keys (prefix + metadata — raw key never returned after creation).
apiKeys.revoke(keyId)→ Promise<object>Revoke a key permanently. Any SDK requests using it will return 401.
REST API Reference
LiveBase URL: https://ec-registry.onrender.com
Register a new device
{"serial_no","product_type","fw_version"}List devices (filter: org_id, tenant_id)
Get device details + reported shadow
Push telemetry from device
{"temp","hum","co2","bat","signal",...}Historical telemetry (?hours=1|6|24|168)
Push config/command to device via MQTT
{"relay":true,"setpoint":22}Trigger OTA firmware update
{"firmware_id":"..."}Remote reboot command
List organizations
List rooms in org
List automation rules
Create rule (threshold or schedule)
{"name","rule_type","condition","action"}Enable/disable/update rule
{"enabled":true}Delete rule
Audit log (last 100 events)
Generate API key
{"name":"My Key"}List API keys
Revoke API key
MQTT Topics
Broker: duck.lmq.cloudamqp.com:8883 (TLS) · Protocol: MQTT 3.1.1
devices/{serial}/telemetryDevice → Cloud. Publish sensor readings. Triggers rule evaluation.
{"temp":24.5,"hum":60,"co2":850,"bat":4.1}devices/{serial}/shadow/desiredCloud → Device. Receive config updates and remote commands.
{"relay":true,"setpoint":22}devices/{serial}/shadow/reportedDevice → Cloud. Report current state after applying desired.
{"relay":true,"temp":22.1}devices/{serial}/otaCloud → Device. Receive OTA firmware payload and version.
{"url":"...","version":"1.2.0"}MQTT credentials — Username: your device serial, Password: device secret (returned on register). TLS required on port 8883. QoS 1 recommended.
ESP32 Libraries
PlatformIO libraries for EdgeConductor hardware. Add to platformio.ini.
WiFi + GSM connectivity
WifiConn + GsmConn auto-failover
MQTT client with OTA
PubSubClient wrapper, handles reconnect
BME280 + MH-Z19 sensors
Temp, humidity, CO₂ readings
Relay + HVAC control
Relay state synced via shadow
NMEA GPS parsing
GP-02 module, lat/lng/speed
Device diagnostics
Battery, signal, heap, reboot reason
Error Codes
Bad Request
Missing or invalid fields in request body.
Unauthorized
Missing or invalid Bearer token / API key.
Forbidden
Key exists but does not have access to this resource.
Not Found
Device or resource does not exist.
Conflict
Device serial already registered.
Rate Limited
Too many requests. Back off and retry.
Server Error
Internal error — contact support if persistent.
Rate Limits
Webhooks
Rules can fire a webhook on threshold breach or schedule. POST to your endpoint with JSON payload. HMAC signature verification coming in v0.2.
Need help integrating?
Open a GitHub issue, email us, or book a 30-min onboarding call. We reply within 24 hours.