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 },
});Quick Start
10 minCreate an org
Sign up → dashboard automatically creates your first org and API key.
Register a device
POST /devices/register with serial + type. Save the returned mqtt_password.
Connect via MQTT
Connect to services.edgeconductor.com:8883 TLS. Publish to devices/{serial}/telemetry.
See it live
Dashboard shows telemetry in under 5 seconds. Rules evaluate every 30s automatically.
import { EdgeConductor } from '@edgeconductor/sdk';
const ec = new EdgeConductor({ apiKey: 'ec_live_...' });
// Register device once (idempotent)
const device = await ec.devices.register({
serial_no: 'EC-FARM-001',
product_type: 'climate_sensor',
});
console.log(device.mqtt_password); // store in firmware flash
// Push telemetry
await ec.telemetry.push('EC-FARM-001', {
temp: 24.5, hum: 60, co2: 820,
});# Register device
curl -X POST https://services.edgeconductor.com/registry/devices/register \
-H "Content-Type: application/json" \
-d '{"serial_no":"EC-FARM-001","product_type":"climate"}'
# Push telemetry (with API key)
curl -X POST .../devices/EC-FARM-001/telemetry \
-H "Authorization: Bearer ec_live_..." \
-H "Content-Type: application/json" \
-d '{"temp":24.5,"hum":60,"co2":820}'Python SDK
v0.2.0Full-featured Python client for device management, telemetry, rules, and fleet operations. Works on any Python 3.8+ environment — Raspberry Pi, servers, scripts, notebooks.
Install
pip install edgeconductor
Initialize
from edgeconductor import Client
ec = Client(api_key="ec_live_xxxx")from edgeconductor import Client
ec = Client(api_key="ec_live_xxxx")
# Register once — safe to call repeatedly
device = ec.devices.register(
serial_no="EC-FARM-001",
product_type="climate_sensor",
)
print(device["mqtt_password"]) # save to firmware
# List all devices in org
devices = ec.devices.list(org_id="<org>")
for d in devices:
print(d["serial_no"], d["status"])
# Push config to device via MQTT
ec.devices.push_config("EC-FARM-001", {
"relay": True, "setpoint": 22
})from edgeconductor import Client
ec = Client(api_key="ec_live_xxxx")
# Push telemetry from a script / test
ec.telemetry.push("EC-FARM-001",
temp=24.5, hum=60, co2=820, bat=4.1,
)
# Last 24 hours of data
rows = ec.telemetry.history(
"EC-FARM-001", hours=24
)
for r in rows:
print(r["timestamp"], r["temp"])
# Stream live — callback fires on change
handle = ec.telemetry.stream(
"EC-FARM-001",
callback=lambda d: print(d),
interval_ms=5000,
)
# ... later:
handle.stop()from edgeconductor import Client
ec = Client(api_key="ec_live_xxxx")
# Alert when COâ‚‚ > 1000 ppm
rule = ec.rules.threshold(
org_id="<org>",
name="CO2 High Alert",
field="co2",
op=">",
value=1000,
action={"key": "relay", "value": True},
webhook_url="https://hooks.example.com/alert",
)
# Schedule — turn relay off at 22:00 on weekdays
ec.rules.schedule(
org_id="<org>",
name="Night Off",
time="22:00",
days=["mon","tue","wed","thu","fri"],
action={"key": "relay", "value": False},
)
# Toggle without deleting
ec.rules.disable(rule["id"])from edgeconductor import Client
ec = Client(api_key="ec_live_xxxx")
# List firmware releases
releases = ec.firmware.list()
latest = releases[0]["id"]
# Push to a single device
ec.firmware.push("EC-FARM-001", latest)
# Audit log — who did what
events = ec.audit.list(org_id="<org>")
for e in events:
print(e["action"], e["created_at"])
# API key management
key = ec.api_keys.generate(
org_id="<org>",
name="CI pipeline",
)
print(key["key"]) # shown once — store securelyReact SDK
v0.1.0Drop-in React components for live device data, telemetry charts, and relay controls. Build a custom IoT dashboard in minutes — just an API key and a device serial.
Install
npm install @edgeconductor/ec-react
Wrap once
<ECProvider apiKey="ec_live_xxxx">
{/* all EC components go here */}
</ECProvider>import {
ECProvider, ECLiveValue, ECTelemetryChart
} from '@edgeconductor/ec-react';
export default function Dashboard() {
return (
<ECProvider apiKey="ec_live_xxxx">
{/* Big-number live metric, auto-refreshes every 5s */}
<ECLiveValue serial="MY-DEVICE-001" field="temp" />
<ECLiveValue serial="MY-DEVICE-001" field="co2" />
<ECLiveValue serial="MY-DEVICE-001" field="hum" />
{/* SVG sparkline — no chart library needed */}
<ECTelemetryChart
serial="MY-DEVICE-001"
field="temp"
hours={24}
color="#6366f1"
label="Temperature (24h)"
/>
</ECProvider>
);
}import {
ECProvider, ECDeviceCard, ECRelayToggle
} from '@edgeconductor/ec-react';
export default function Controls() {
return (
<ECProvider apiKey="ec_live_xxxx">
{/* Status card: online/offline, fw version, last seen */}
<ECDeviceCard serial="MY-DEVICE-001" />
{/* Relay toggle — optimistic UI, pushes via MQTT shadow */}
<ECRelayToggle
serial="MY-DEVICE-001"
field="relay"
label="HVAC"
onColor="#22c55e"
/>
</ECProvider>
);
}import { useDevice, useTelemetry, useShadow } from '@edgeconductor/ec-react';
function MyWidget({ serial }) {
const { device, loading } = useDevice(serial);
const { data, latest } = useTelemetry(serial, { hours: 6, intervalMs: 5000 });
const { pushDesired } = useShadow(serial);
return (
<div>
<p>Status: {device?.status}</p>
<p>Temp: {latest?.temp}°C — {data.length} points</p>
<button onClick={() => pushDesired({ relay: true })}>Turn ON</button>
</div>
);
}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://services.edgeconductor.com/registry
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
Webhooks
NewRegister your server URL to receive real-time events. Every request carries an HMAC-SHA256 signature you can verify.
List registered webhooks for an org
Register a webhook endpoint
{"url","events":["telemetry","alert","ota","device_status"]}Update webhook — toggle active, change URL or events
{"active":false}Delete a webhook permanently
Send a signed test payload to verify endpoint reachability
Payload format
{
"event": "telemetry", // or alert, ota, device_status
"org_id": "uuid",
"timestamp": "2026-09-03T10:00:00Z",
"data": { ... } // event-specific payload
}Signature verification (Node.js)
const sig = req.headers['x-ec-signature'];
const expected = 'sha256=' +
crypto.createHmac('sha256', WEBHOOK_SECRET)
.update(rawBody)
.digest('hex');
if (sig !== expected) return res.sendStatus(401);Locations
NewOrganise devices in a physical hierarchy — Site → Building → Floor → Room. Assign any device to any node.
List all locations (Site/Building/Floor/Room) for org
Create a location node
{"name","type":"site|building|floor|room","parent_id?"}Rename or reparent a location
{"name","parent_id"}Delete location (cascades to children)
Assign a device to a location node
{"location_id":"<uuid>"}MQTT Topics
Broker: services.edgeconductor.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
Register endpoints to receive telemetry, alert, ota, and device_status events. Each request is signed with X-EC-Signature: sha256=<hmac>.
Need help integrating?
Open a GitHub issue, email us, or book a 30-min onboarding call. We reply within 24 hours.