Skip to main content

API Reference

EmberCORE exposes a REST API under /api. EmberCORE's own web interface is built on it, and the same routes are available to integrations. This page lists the routes a customer integration can use, with the access each one needs.

Base URL​

The API is served by EmberCORE itself. There is no separate API host.

https://dashboard.embernet.ai/api

Paths are versionless (/api/nodes, /api/alerts). There is no /v1 prefix.

Authentication​

There are no API keys. Every request is made as a person, and is allowed or refused by that person's role in the tenant it touches.

  • From a browser, requests carry your EmberCORE sign-in session. See SSO Integration. Calls made by the EmberCORE interface inherit it automatically.
  • From the EmberNet Endpoint client, the client sends a Microsoft bearer token (Authorization: Bearer <token>) on the routes that accept one: /api/tenants/me, /api/endpoints, and /api/endpoints/cards.

Rate limiting​

There is no general rate limit on the API. The one exception is the public access request form, POST /api/access-request, which accepts three requests per ten minutes from one address and answers 429 Too Many Requests after that.

Tenant scope​

Routes that return per-tenant data take an optional ?tenant=<id>:

  • Below Global Command, leaving it out selects your primary tenant, and asking for a tenant you do not belong to returns 403 Forbidden.
  • Global Command may pass any tenant, or leave it out for a platform-wide view.

A few routes differ:

  • /api/nodes and /api/metrics always answer for your primary tenant below Global Command, whatever ?tenant= says.
  • The App Store routes take ?tenant_id= instead.
  • Routes that act on one device or alert check who owns it: an unknown ID returns 404, and another tenant's returns 403.
  • The Flux routes return an empty result, not 403, for a tenant you cannot see.

Responses​

Successful responses are plain JSON: an array for lists and an object for a single resource, with no {status, data} envelope. Errors come back with the matching HTTP status and a short message, usually as plain text and on some routes as {"error": "..."}.

Access levels​

The Access column below uses these terms:

TermWho
Any roleEvery tenant role, Viewer included
EngineerEngineers and Admins
AdminTenant Admins
Global CommandFireball platform staff only

Session and tenants​

MethodRouteAccessDescription
GET/api/ui/sessionAny roleThe view model the console renders from: who you are, your role, your tenant, and what your view shows. 403 if you have no tenant
GET/api/tenantsAny roleThe tenants you belong to
GET/api/tenants/meAny role (bearer accepted)Your identity's tenant context
GET/api/tenants/{id}Members of that tenantOne tenant
GET/api/tenants/{id}/membersAdminThe tenant's members
GET/healthzPublicHealth check, {"status":"ok"}

Nodes and metrics​

MethodRouteAccessDescription
GET/api/nodesAny roleEdge nodes and the apps running on each
GET/api/metricsAny rolePod and ingress counts for your tenant
GET/api/wsAny roleWebSocket of live node and pod updates
GET/api/cluster/metricsEngineerCluster CPU, memory, and disk
GET/api/k8s/nodesEngineerNode names, roles, and readiness
GET/api/eventsEngineerCluster events for your tenant; /api/events/filtered filters them

Sites and devices​

MethodRouteAccessDescription
GET/api/sitesAny roleSites; /api/sites/{id}, /api/sites/{id}/buildings/{bid}, and /api/sites/health drill in
GET POST/api/admin/sitesAdminList and create sites; /api/admin/sites/{id} edits and removes them
GET/api/devicesAny roleRegistered devices
POST PUT DELETE/api/devicesAdminRegister, update (?id=), and remove (?id=) a device
POST/api/devices/health/check?id=Any roleRun a health check on a device now
GET PUT/api/devices/credentials?id=AdminA device's stored credentials
ANY/api/device/proxy?id=&path=Any roleProxy to a device's own web interface
GET/api/admin/devices/import/templateAdminThe bulk import template; detect, validate, and execute under the same path run an import

/api/facilities and /api/admin/facilities are aliases of the site routes.

SNMP​

MethodRouteAccessDescription
GET/api/devices/snmp/config?id=Any roleA device's SNMP settings, with secrets masked
PUT/api/devices/snmp/config?id=AdminSave SNMP settings. An empty secret keeps the stored one
GET/api/devices/snmp/metrics?id=Any roleThe latest SNMP metrics
GET/api/devices/snmp/interfaces?id=Any roleInterface status and traffic

See SNMP Configuration.

Industrial collectors​

MethodRouteAccessDescription
GET/api/industrial/protocolsAny roleEvery supported protocol, and what the gateway protocols ride
GET/api/industrial/config?id=[&protocol=]Any roleA device's collector configuration
PUT/api/industrial/configAdminSave a collector. Refused with the reason if the configuration cannot work
GET/api/industrial/summary?id=Any roleEach protocol on the device, with connected, lastPoll, lastError, and tagCount
GET/api/industrial/metrics?id=&protocol=Any roleRecent tag values, with quality and sparkline history
GET/api/industrial/tsdb/statusAny roleWhether the time-series store is enabled
GET/api/industrial/tsdb/query?id=&protocol=&tag=&range=Any roleA tag's history (default range one hour)
GET/api/industrial/opcua/client-cert?tenant=AdminYour tenant's OPC UA client certificate: {tenant, applicationUri, thumbprint, certificatePem}. Created on first call

A collector body is {deviceId, protocol, enabled, address, interval, protocolConfig}, where interval is in seconds and protocolConfig is the protocol's settings as a JSON object serialized into a string. Save "enabled": false to stop a collector. Every protocol's settings are described in Device Connectivity.

Alerts​

MethodRouteAccessDescription
GET/api/alertsAny roleAlerts for your tenant. Filters: tenant, status, facility, severity, limit
GET/api/alerts/summaryAny roleAlert counts by severity
POST/api/alerts/acknowledge?id=Any roleAcknowledge an alert. {"acknowledged":true}
POST/api/alerts/resolve?id=AdminResolve an alert. {"resolved":true}

An alert has an id, severity (critical, warning, or info), alertType, title, message, status (active, acknowledged, or resolved), its tenant, the device, site, and building it concerns where there is one, and timestamps. Alert types include device_offline, device_online, degraded, and site_down from rules, cinder_volume_degraded, cinder_volume_faulted, and cinder_capacity_guardrail from storage, and cluster_unreachable and cluster_degraded from cluster health.

Alert rules and webhooks​

MethodRouteAccessDescription
GET/api/alerts/rulesGlobal CommandList rules
POST/api/alerts/rulesGlobal CommandCreate a rule. 201 with {"id"}
PUT/api/alerts/rulesGlobal CommandUpdate a rule; the id goes in the body
DELETE/api/alerts/rules?id=Global CommandDelete a rule

Rules are managed by Fireball, so ask us to add or change one. A rule has a name, enabled, a scope (device, building, facility, or global) and scopeId, an alertType, a severity, cooldownMinutes, the thresholds degradedThreshMin and siteDownThreshold, and its channels: notifyEmail, notifyDashboard (the bell), notifyWebhook, and webhookUrl.

When a rule with a webhook fires, EmberCORE sends a JSON POST to the webhookUrl:

{
"type": "alert",
"alert": { "id": "...", "severity": "critical", "alertType": "device_offline", "title": "...", "message": "..." },
"sentAt": "2026-10-05T02:14:07Z"
}

The request carries User-Agent: Embernet-Dashboard/alerts and times out after ten seconds. A network failure, a 429, or a 5xx is retried up to three attempts in all, two and then four seconds apart. Any other 4xx is not retried. A rule with the webhook ticked must have a full http or https URL, or it is refused when saved.

Phone alerts​

MethodRouteAccessDescription
GET/api/push/keyAny signed-in userThe public key a browser subscribes with, {"publicKey"}
POST/api/push/subscribeAny signed-in userRegister a browser push subscription: {endpoint, keys: {p256dh, auth}}
POST/api/push/unsubscribeAny signed-in userRemove one: {endpoint}
POST/api/push/testAny signed-in userSend yourself a test notification. {"sent": n}

Phone alerts are Web Push notifications for critical alerts. In EmberCORE, the bell's "Phone alerts" switch in the Global Command, Admin, and Engineer views does all of this for you, and sends a test notification as soon as you turn it on. Device alerts push only from rules that also ring the bell, and storage and cluster alerts push when they are critical. Who receives an alert is decided when it fires: the alert's tenant, plus Fireball staff. Subscriptions must point at a real browser push service (Google, Mozilla, Microsoft, or Apple). On iPhone and iPad, push works only from EmberCORE installed to the Home Screen, not from a Safari tab.

Storage​

MethodRouteAccessDescription
GET/api/storage/dashboardAdminCapacity, volume health, and guardrail status
GET/api/storage/devicesAdminDisks and nodes in the storage pool
GET/api/storage/backupsAdminBackup inventory
GET/api/storage/snapshotsAdminSnapshots
GET/api/storage/recurring-jobsAdminScheduled snapshot and backup jobs
GET/api/storage/volume-detailAdminOne volume in detail
POST/api/storage/actionAdminVolume actions
GET POST PUT/api/storage/settingsAdminStorage settings, including guardrails
POST PUT/api/storage/backup-targetAdminSet the backup target
POST/api/storage/backup-target/testAdminTest a backup target before you rely on it

Below Global Command, the routes that change storage work on a tenant's own external cluster. See Cinder.

App Store and apps​

MethodRouteAccessDescription
GET/api/store/apps?tenant_id=Any roleThe catalog you can see
POST/api/store/deployEngineerDeploy an app to a node. The response can carry a note, for example when a CODESYS app went on the pod network because its host ports were taken
GET/api/store/deployments?tenant_id=EngineerYour deployments
DELETE/api/store/deployments/{uid}EngineerRemove a deployment
GET/api/store/safe-control-targets?app_id=&node_name=EngineerThe Safe Control releases a CODESYS Safe Time Provider can send to
GET/api/apps/servicesAny roleRunning apps for your tenant
POST/api/apps/uninstallEngineerUninstall a running app
ANY/api/proxy?target=Any roleProxy to a running app's interface. The target must belong to your tenant

AnvilMQ broker​

MethodRouteAccessDescription
GET/api/admin/broker/statusEngineerBroker health for your tenant; /drivers, /tags, /connections, and /config under the same path
GET POST DELETE/api/admin/broker/usersAdminYour tenant's broker users

Flux​

MethodRouteAccessDescription
GET/api/flux/tenant/summaryAny roleYour tenant's Flux overview
GET/api/flux/tenant/servicesAny roleYour Flux services; /identities, /edge-routers, and /topology under the same path
GET/api/flux/latency?tenant=Any roleMeasured latency to each of your services

Users​

MethodRouteAccessDescription
GET/api/admin/usersAdminUsers in your tenant
POST/api/admin/usersAdminInvite a user: {email, displayName, role, tenant, tenantRole}. tenantRole is admin, engineer, operator, or viewer, up to your own
GET PUT DELETE/api/admin/users/{email}AdminOne user
POST/api/admin/users/{email}/suspendAdminSuspend a user; /activate restores them
GET/api/admin/grantable-tenantsAdminThe tenants you may invite people into
GET/api/admin/permissionsAdminEvery permission, and which roles hold it

Audit​

MethodRouteAccessDescription
GET/api/admin/auditOperator and aboveThe recent activity feed
GET/api/audit/searchAdminSearch your tenant's audit log: q, actor, action, from, to, limit. Returns {entries, stats}
GET PUT POST DELETE/api/audit/export?tenant=AdminExport your audit trail to your own S3, Azure Blob, PostgreSQL, or HTTPS endpoint
POST/api/audit/export/runAdminRun the export now
GET/api/audit/export/schema?table=AdminThe exported schema
GET/api/audit/retentionAdminHow long the audit log is kept. Changing it is Global Command only
GET POST PUT DELETE/api/reports/schedulesAdminScheduled reports; /api/reports/generate runs one

Ignition​

MethodRouteAccessDescription
GET/api/ignition/statusOperator and aboveYour Ignition gateway's status
GET/api/ignition/tenantOperator and aboveYour tenant's Ignition setup
GET POST PUT/api/ignition/usersAdminThe gateway accounts EmberCORE signs your people in with
GET PUT POST/api/ignition/role-mapAdminWhich Ignition roles each EmberCORE role receives

Shells and support​

MethodRouteAccessDescription
GET/api/shellAdminWebSocket shell on a node your tenant owns
GET/api/shell/podAdminWebSocket shell into one of your tenant's pods
POST/api/support/ticketAny signed-in userOpen a support ticket

EmberNet Endpoint​

MethodRouteAccessDescription
GET/api/endpoints?tenant=Bearer tokenEndpoints in your tenant
GET/api/endpoints/cardsBearer tokenEndpoint liveness cards

Next steps​