Developers

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.

Node.js
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.0

Manage 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 / whoami / logoutAuthentication
ec login          # save API key + registry URL → ~/.ec/config.json
ec whoami         # show current login
ec logout         # remove saved credentials
ec deviceFleet management
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 telemetryLive + historical data
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 otaFirmware updates
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 manufactureFactory provisioning
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 orgOrganizations
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.0
ec.devices
devices.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.

ec.telemetry
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.

ec.rules
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.

ec.orgs
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.

ec.audit
audit.list(orgId, { limit? })Promise<Event[]>

Last N audit events. Actions: rule_fired, device_offline, ota_pushed, config_pushed.

ec.notifications
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.

ec.anomalies
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.

ec.firmware
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.

ec.apiKeys
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

Live

Base URL: https://ec-registry.onrender.com

MethodEndpointDescription
POST/devices/register

Register a new device

{"serial_no","product_type","fw_version"}
GET/devices

List devices (filter: org_id, tenant_id)

GET/devices/:serial

Get device details + reported shadow

POST/devices/:serial/telemetry

Push telemetry from device

{"temp","hum","co2","bat","signal",...}
GET/devices/:serial/telemetry

Historical telemetry (?hours=1|6|24|168)

PATCH/devices/:serial/shadow/desired

Push config/command to device via MQTT

{"relay":true,"setpoint":22}
POST/devices/:serial/ota

Trigger OTA firmware update

{"firmware_id":"..."}
POST/devices/:serial/reboot

Remote reboot command

GET/orgs

List organizations

GET/orgs/:id/rooms

List rooms in org

GET/orgs/:id/rules

List automation rules

POST/orgs/:id/rules

Create rule (threshold or schedule)

{"name","rule_type","condition","action"}
PATCH/rules/:id

Enable/disable/update rule

{"enabled":true}
DELETE/rules/:id

Delete rule

GET/orgs/:id/audit

Audit log (last 100 events)

POST/orgs/:id/api-keys

Generate API key

{"name":"My Key"}
GET/orgs/:id/api-keys

List API keys

DELETE/api-keys/:id

Revoke API key

MQTT Topics

Broker: duck.lmq.cloudamqp.com:8883 (TLS) · Protocol: MQTT 3.1.1

PUBdevices/{serial}/telemetry

Device → Cloud. Publish sensor readings. Triggers rule evaluation.

{"temp":24.5,"hum":60,"co2":850,"bat":4.1}
SUBdevices/{serial}/shadow/desired

Cloud → Device. Receive config updates and remote commands.

{"relay":true,"setpoint":22}
PUBdevices/{serial}/shadow/reported

Device → Cloud. Report current state after applying desired.

{"relay":true,"temp":22.1}
SUBdevices/{serial}/ota

Cloud → 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.

ECConn

WiFi + GSM connectivity

WifiConn + GsmConn auto-failover

ECMqtt

MQTT client with OTA

PubSubClient wrapper, handles reconnect

ECClimate

BME280 + MH-Z19 sensors

Temp, humidity, CO₂ readings

ECHvac

Relay + HVAC control

Relay state synced via shadow

ECGPS

NMEA GPS parsing

GP-02 module, lat/lng/speed

ECDiag

Device diagnostics

Battery, signal, heap, reboot reason

Error Codes

400

Bad Request

Missing or invalid fields in request body.

401

Unauthorized

Missing or invalid Bearer token / API key.

403

Forbidden

Key exists but does not have access to this resource.

404

Not Found

Device or resource does not exist.

409

Conflict

Device serial already registered.

429

Rate Limited

Too many requests. Back off and retry.

500

Server Error

Internal error — contact support if persistent.

Rate Limits

Starter100 req / min
Pro1,000 req / min
Business10,000 req / min
EnterpriseCustom / unlimited

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.