WEDA Core v1.2.0 API Changes
This page lists API changes from v1.1.2 to v1.2.0 that affect integrations or add new capabilities. For feature highlights, fixes and release status, see the v1.2.0 Release Notes.
Endpoints are relative to /api/v1, except the Web SSH browser entry, whose full path is shown. Each row identifies one HTTP method and endpoint. Breaking identifies a changed request rule, response field, response behavior or removed endpoint that requires existing consumers of that contract to update their code. Additive identifies new operations, optional capabilities and additional response fields that preserve existing usage.
Documentation clarifications and schema corrections that do not establish a change in API behavior are excluded.
Update clients that read renamed response timestamps, depend on the old AI Model states or call removed endpoints. Review every Breaking row used by your integration; this page complements the release summary.
Identity & Access
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create a new organization | POST | /orgs | Modified | Breaking | Response: dateCreated → createdAt; dateModified → updatedAt. Update clients that read the old keys; those keys are no longer returned. |
| Update an existing organization | PATCH | /orgs/{orgId} | Modified | Breaking | Response: dateModified → updatedAt. Update clients that read dateModified; that key is no longer returned. |
| Retrieve all organization roles linked to the specified user | GET | /users/{userId}/orgs | Modified | Breaking | Response: items[].dateCreated → items[].createdAt; items[].dateModified → items[].updatedAt. Update response parsing; the old keys are no longer returned. |
| Create a Client Credential | POST | /oauth2/client-credentials | Added | Additive | Create a credential with name, optional scopes, deviceIds and expiredAt. 201 returns the client ID and secret. |
| Get all Client Credentials | GET | /oauth2/client-credentials | Added | Additive | List existing Client Credentials and their metadata. |
| Delete a Client Credential by ID | DELETE | /oauth2/client-credentials/{clientCredentialId} | Added | Additive | Revoke and delete the specified Client Credential. |
Device Management
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Get devices with pagination | GET | /devices | Modified | Breaking | Response: items[].creationTime → items[].createdAt. Update device-list timestamp mappings. |
| Update device status | POST | /devices/{deviceId}:{status} | Modified | Breaking | Response: creationTime → createdAt; the old key is no longer returned. Adds type (WedaNode, SubNode, CustomDevice). Handle a null hwModel for device types without a hardware model. |
| Update a device | PATCH | /devices/{deviceId} | Modified | Breaking | Request no longer accepts orgId; deviceId, hwModel and orgId are immutable. deviceName must match [A-Za-z0-9_-]{1,128}. Response adds type; do not require a non-null hwModel for every device type. |
| Get device hardware capabilities | GET | /devices/{deviceId}/capabilities | Modified | Breaking | In each capability entry, the response timestamp changes from creationTime to createdAt; update clients that read the old key. Adds reported capability fields commands, devices, dspFilters, sdkVersion, sensorTypes and transforms. |
| Register a device to an organization | POST | /orgs/{orgId}/devices | Modified | Breaking | WEDA Node registration validates deviceId against [a-z0-9]{12}, hwModel against [A-Z0-9-]{1,64}, and deviceName against [A-Za-z0-9_-]{1,128}. Names are unique within the organization, ignoring case. Response adds type; hwModel can be absent or null for applicable device types. The 12-character Node ID rule does not apply to Custom Device UUIDs. |
| List devices by Organization | GET | /orgs/{orgId}/devices | Modified | Breaking | Adds deviceIds[] filtering; maxResultCount is limited to 1–100. Response: items[].creationTime → items[].createdAt; adds type, parentDeviceId and connectivity (state, updatedAt). Lists can contain WEDA Nodes, SubNodes and Custom Devices; handle nullable hwModel. Use createdAt for timestamp sorting. |
| Get a single device by Organization | GET | /orgs/{orgId}/devices/{deviceId} | Added | Additive | Get one WEDA Node or Custom Device within an organization. |
| Update a device by Organization | PATCH | /orgs/{orgId}/devices/{deviceId} | Added | Additive | Rename one WEDA Node or Custom Device within an organization. Send deviceName; do not include immutable deviceId, hwModel or orgId. |
Telemetry Configuration
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Get device telemetry configurations | GET | /devices/{deviceId}/telemetry-configs | Modified | Breaking | GET now prioritizes desired settings instead of reporting only the device-reported configuration. It falls back to reported settings when no desired settings exist. Use status (success, failed, invalid), appliedAt and errorMessage to check application. A new PATCH retains the previous result until the device reports again; with an accurate device clock, require appliedAt at or after updatedAt. Adds report, local record, transform and DSP pipelines, thresholds and sensor parameters; legacy config remains supported. |
| Update device telemetry configurations | PATCH | /devices/{deviceId}/telemetry-configs | Modified | Breaking | A sensor may use legacy config or report, never both. In a supplied config/report, enabled and interval are required instead of defaulted. record.enabled is required; record.interval is required when recording is enabled. Omitted device-level enabled preserves its value. Supplied pipelines and threshold collections replace their stored values. Unknown sensors and invalid configuration return 400; 202 means accepted, not applied. |
| Reset device telemetry configurations | POST | /devices/{deviceId}/telemetry-configs:reset | Added | Additive | Clear the desired telemetry configuration. 202 confirms dispatch; reverting to factory defaults depends on the device firmware. |
| Get sensors a SubNode supports | GET | /devices/{deviceId}/capabilities/sensors | Added | Additive | List the sensors supported by a SubNode, with sensor names and type DTMIs. This is capability discovery, independent of its current telemetry configuration. |
| Get DTDL type definitions for one category, with configuration schema and constraints | GET | /devices/{deviceId}/capabilities/schema | Added | Additive | Get DTDL type definitions and configuration constraints. Query type=configs for sensor configuration or type=commands for commands; resolve a sensor DTMI against the returned @id. |
Remote Device Commands
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Reboot a device | POST | /devices/{deviceId}/commands:reboot | Added | Additive | Request a reboot with Admin permission. 202 returns a command result; track its reqSeqId through GET .../commands/results. |
| Shut down a device | POST | /devices/{deviceId}/commands:shutdown | Added | Additive | Request shutdown with Admin permission. The device remains off until powered on manually. Track the returned reqSeqId in command history. |
| Invoke a device command | POST | /devices/{deviceId}/commands:invoke | Added | Additive | Invoke a device-declared command using deviceCommand and parameters; available commands depend on the device capability catalog. Track the returned reqSeqId in command history. |
| Resync a device's historical data for a time range | POST | /devices/{deviceId}/commands:resync | Added | Additive | Request asynchronous historical-data recovery using startedAt and endedAt. Start must precede end and fall within the seven-day recovery horizon. Recovery requires local recordings; matching cloud data is replaced. Track the returned reqSeqId. |
| List a device's command history | GET | /devices/{deviceId}/commands/results | Added | Additive | Read paged command history and match reqSeqId. data.phase distinguishes pending, ack, progress and result; reboot/shutdown use pending → result. data.status uses 0 for success/received and 1 for failure. |
Custom Device Data Sources
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Get the device's data parser | GET | /orgs/{orgId}/devices/{deviceId}/data-source/data-parser | Added | Additive | Read the Custom Device parser. An existing device without a parser returns 200 with a default-valued object, rather than a missing-parser 404. |
| Create or update the device's data parser | PUT | /orgs/{orgId}/devices/{deviceId}/data-source/data-parser | Added | Additive | Create or fully replace the parser and its channel mappings. configs replaces the entire array; omitted channels are removed. Map parsed values and blobs to the configured output streams. |
| Update the device's data parser | PATCH | /orgs/{orgId}/devices/{deviceId}/data-source/data-parser | Added | Additive | Partially update an existing parser. Omitted fields are preserved, but a supplied configs array fully replaces the old array. |
| Get the device's data source | GET | /orgs/{orgId}/devices/{deviceId}/data-source | Added | Additive | Read the Custom Device connection configuration. An existing device without a data source returns 200 with a default-valued object. |
| Create or update the device's data source | PUT | /orgs/{orgId}/devices/{deviceId}/data-source | Added | Additive | Create or fully replace a data source. Supports MQTT(v3.1), WEDA Data-Stream and HTTP-Server. Once set, connectorType cannot change; omitting description clears it. |
| Update the device's data source | PATCH | /orgs/{orgId}/devices/{deviceId}/data-source | Added | Additive | Partially update a data source; omitted fields are preserved. A previously set connectorType remains immutable. |
| Write telemetry payload and optionally initialize blob upload | POST | /devices/{deviceId}/data-source/http-server/data | Added | Additive | Ingest parser-mapped telemetry for an activated Custom Device using HTTP-Server. For a blob mapping, initialize an upload and retain the returned uploadId and expiry for the binary-upload step. |
| Upload blob content (two-step upload, step 2) | PUT | /devices/{deviceId}/data-source/http-server/data | Added | Additive | Upload raw blob bytes using the uploadId initialized by POST, before it expires. An upload ID is one-time use; an in-flight duplicate returns 409 and reuse after completion returns 404. |
Container Registries
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create Registry Config | POST | /orgs/{orgId}/containers/registries | Modified | Breaking | Response: creationTime → createdAt; the old key is no longer returned. Registry hosts must now be unique within the organization; a duplicate returns 409 RegistryHostExists. Update response parsing and handle host conflicts. |
| List Registry Configs by Organization | GET | /orgs/{orgId}/containers/registries | Modified | Breaking | Response: items[].creationTime → items[].createdAt; the old key is no longer returned. Default sorting uses createdAt desc instead of creationTime desc; the legacy sorting alias remains accepted. |
| Get registry config | GET | /orgs/{orgId}/containers/registries/{registryId} | Modified | Breaking | Response: creationTime → createdAt; the old key is no longer returned. Update clients that read the registry creation timestamp. |
| Update registry config | PUT | /orgs/{orgId}/containers/registries/{registryId} | Modified | Breaking | Response: creationTime → createdAt; the old key is no longer returned. Changing to an existing registry host returns 409 RegistryHostExists. Registry-name uniqueness on update is checked within the organization instead of the tenant. |
Container Stacks
Container list APIs retain the legacy creationTime sorting alias. Response fields use createdAt; update response parsing even when an old sorting expression is still accepted.
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Get stack deployments | GET | /orgs/{orgId}/stack-configs/deployments | Modified | Breaking | Response: items[].creationTime → items[].createdAt; default sorting: creationTime desc → createdAt desc. Invalid requests expose structured validationItems[] in 400 responses. |
| Deploys container stack | POST | /orgs/{orgId}/stack-configs/{stackConfigId}/revisions/{stackRevisionId}:deploy | Modified | Breaking | Response: stackDeployments[].creationTime → stackDeployments[].createdAt. Invalid deployment parameters return 400 instead of 500; read validationItems[] for field-level failures. |
| List stacks in device | GET | /devices/{deviceId}/docker/stacks | Modified | Breaking | Response: items[].creationTime → items[].createdAt; default sorting: creationTime desc → createdAt desc. |
| Get latest container stack configuration | GET | /orgs/{orgId}/stack-configs/{stackConfigId} | Modified | Breaking | Response: creationTime → createdAt. Read createdAt; creationTime is no longer returned. |
| Update Stack Revision | PATCH | /orgs/{orgId}/stack-configs/{stackConfigId} | Modified | Breaking | Response: creationTime → createdAt. Validation errors use 400 with validationItems[]; update field-error parsing. |
| List stack revisions | GET | /orgs/{orgId}/stack-configs/{stackConfigId}/revisions | Modified | Breaking | Response: items[].creationTime → items[].createdAt; default sorting: CreationTime desc → createdAt desc. Validation errors expose validationItems[]. |
| Create container stack | POST | /orgs/{orgId}/stack-configs | Modified | Breaking | The 201 response renames creationTime to createdAt. |
| List Stack Configs by Organization | GET | /orgs/{orgId}/stack-configs | Modified | Breaking | Response: items[].creationTime → items[].createdAt; default sorting: creationTime desc → createdAt desc. |
| Get stack revision configuration | GET | /orgs/{orgId}/stack-configs/{stackConfigId}/revisions/{stackRevisionId} | Modified | Breaking | Response: creationTime → createdAt. Read createdAt; creationTime is no longer returned. |
| Compare Stack Revisions | GET | /orgs/{orgId}/stack-configs/revisions/diff | Modified | Breaking | Response: sourceStack.creationTime → sourceStack.createdAt; targetStack.creationTime → targetStack.createdAt. |
Container Commands
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Manage Container State | POST | /devices/{deviceId}/docker/stacks/commands:{action} | Modified | Breaking | Validation failures use validationItems[] in place of the former errors object; update field-error parsing. Dispatch acknowledgement wait increases from 5 to 30 seconds, so allow a client timeout longer than 30 seconds. |
| List Container State Changing Results | GET | /devices/{deviceId}/docker/stacks/commands/results | Modified | Breaking | Adds data.phase (pending, ack, progress, result) and structured data.error (code, message); progress is reserved and unused for Container commands in this version. executedAt and completedAt are now device-reported and can be null until reported; update timestamp handling. Use data.createdAt for request-acceptance time. data.status remains 0 for success/received and 1 for failure. |
AI Model Deployments
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create Deployment | POST | /orgs/{orgId}/ai-models/{modelId}/editions/{edition}:deploy | Modified | Breaking | Response targets[].state: removes DOWNLOADED; adds DOWNLOADING, VERIFYING and STAGING. Adds targets[].rejectReason for rejected targets. Update deployment-state switches and generated enums. |
| List All AI Models for a Specific Device | GET | /devices/{deviceId}/ai-models | Modified | Breaking | Query state and response items[].state: remove DOWNLOADED; add DOWNLOADING, VERIFYING and STAGING. Adds errorCode and errorMessage; rejectedReason identifies the failure category. Update filters and state handling. |
| List Devices for a Specific Model Edition | GET | /orgs/{orgId}/ai-models/{modelId}/editions/{edition}/deployments | Modified | Breaking | Query state and response items[].state: remove DOWNLOADED; add DOWNLOADING, VERIFYING and STAGING. Adds errorCode and errorMessage; rejectedReason identifies the failure category. Update filters and state handling. |
| Delete Model File from a Specific Device | DELETE | /devices/{deviceId}/ai-models/{modelId}/editions/{edition} | Modified | Breaking | A missing device now returns 404 instead of 403. Update error handling to distinguish a missing device from insufficient permission; successful requests remain asynchronous (202). |
AI Model Editions
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Get Model Edition Detail | GET | /orgs/{orgId}/ai-models/{modelId}/editions/{edition} | Modified | Breaking | Response removes file.fileUri. Update clients that read this field; it is no longer included in edition metadata. |
| Update Edition Metadata | PATCH | /orgs/{orgId}/ai-models/{modelId}/editions/{edition} | Modified | Breaking | Response removes file.fileUri. Update response parsing for the edition metadata returned after an update. |
| Register New Edition of an Existing Model | POST | /orgs/{orgId}/ai-models/{modelId}/editions | Modified | Breaking | Response removes file.fileUri from the newly registered edition. Remove dependencies on that response field. |
| List Editions of a Model | GET | /orgs/{orgId}/ai-models/{modelId}/editions | Modified | Breaking | Response removes items[].file.fileUri. Update edition-list response parsing and dependent controls. |
AI Model File Downloads
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Download a model file | GET | /ai-models/{modelId}/editions/{edition}/files | Removed | Breaking | The legacy model-file download endpoint is removed. Remove direct download calls and any download control that depends on this endpoint. |
| Get model-file download headers | HEAD | /ai-models/{modelId}/editions/{edition}/files | Removed | Breaking | The legacy model-file download endpoint is removed. Remove direct download calls and any download control that depends on this endpoint. |
Data Streams
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create a data stream | POST | /orgs/{orgId}/devices/{deviceId}/data-streams | Modified | Additive | Request and response dataType add blob and data-pack alongside the existing value types. |
| List data streams | GET | /orgs/{orgId}/devices/{deviceId}/data-streams | Modified | Additive | Response entries add blob and data-pack to dataType. Handle these new stream types when listing metadata. |
| Get a data stream | GET | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId} | Modified | Additive | Response dataType adds blob and data-pack. Handle these types when reading stream metadata. |
| Partially update a data stream | PATCH | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId} | Modified | Additive | Response dataType adds blob and data-pack. This does not add an editable dataType field to the PATCH request. |
| Update a data stream | PUT | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId} | Modified | Additive | Request and response dataType add blob and data-pack. |
| Get data history | GET | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/values/historical | Modified | Additive | Response dataType adds blob and data-pack. Handle these new value types in historical-query results. |
| Get aggregated values | GET | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/aggregate | Added | Additive | Read time-bucket aggregates using required startTime, endTime and ISO 8601 duration period; optional slidingStep supports overlapping windows. |
| Get blob metadata | GET | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/blobs/{blobId}/metadata | Added | Additive | Read blob metadata and its downloadUrl for a blob stream. Use the existing blob-content endpoint to retrieve the bytes. |
| Get a data pack by ID | GET | /orgs/{orgId}/devices/{deviceId}/data-streams/{dataStreamId}/data-packs/{dataPackId} | Added | Additive | Read a stored structured record from a data-pack stream. Treat dataPackId as an opaque identifier, not necessarily a UUID. |
Analyzers
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create device analyzer | POST | /orgs/{orgId}/devices/{deviceId}/analyzers | Modified | Additive | Adds type: JavaScript alongside TransferFunction, with config.script (maximum 10,000 characters), multiple outputs, output valueJsonPath/timeJsonPath, and optional dataAssemblyPolicy (onTimeout, queueLimit, timeoutSeconds). Existing TransferFunction requests continue to use config.expression and one input/output. |
| Update a device analyzer | PUT | /orgs/{orgId}/devices/{deviceId}/analyzers/{analyzerId} | Modified | Additive | Adds type: JavaScript alongside TransferFunction, with config.script (maximum 10,000 characters), multiple outputs, output valueJsonPath/timeJsonPath, and optional dataAssemblyPolicy (onTimeout, queueLimit, timeoutSeconds). Existing TransferFunction requests continue to use config.expression and one input/output. |
| List device analyzers | GET | /orgs/{orgId}/devices/{deviceId}/analyzers | Modified | Additive | Response entries can now describe JavaScript Analyzers, including config.script, output valueJsonPath/timeJsonPath and dataAssemblyPolicy. Continue reading config.expression for TransferFunction entries. |
| Get a device analyzer | GET | /orgs/{orgId}/devices/{deviceId}/analyzers/{analyzerId} | Modified | Additive | Response adds the JavaScript type, config.script, output valueJsonPath/timeJsonPath and dataAssemblyPolicy. Existing TransferFunction definitions continue to use config.expression. |
| Partially update a device analyzer | PATCH | /orgs/{orgId}/devices/{deviceId}/analyzers/{analyzerId} | Modified | Additive | Adds JavaScript config.script, output valueJsonPath/timeJsonPath and dataAssemblyPolicy updates. Existing TransferFunction expression updates remain supported. |
| Enable or disable an analyzer | POST | /orgs/{orgId}/devices/{deviceId}/analyzers/{analyzerId}:{action} | Modified | Additive | Enabling a JavaScript Analyzer with multiple inputs initializes multi-input processing asynchronously. 204 confirms the enabled-state change; it does not confirm that output has begun. Continue using lowercase enable or disable. |
MQTT Brokers & TLS Certificates
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create MQTT broker config | POST | /orgs/{orgId}/data-bridges/mqtt-broker-configs | Modified | Additive | Request adds optional tls.caCertificateId to reference an uploaded CA for an mqtts broker. Response adds tls, tlsEnabled and hasCustomCaCertificate. |
| List MQTT broker configs | GET | /orgs/{orgId}/data-bridges/mqtt-broker-configs | Modified | Additive | Response items add tlsEnabled and hasCustomCaCertificate, so clients can display TLS and custom-CA status. |
| Get MQTT broker config | GET | /orgs/{orgId}/data-bridges/mqtt-broker-configs/{mqttConfigId} | Modified | Additive | Response adds tls, tlsEnabled and hasCustomCaCertificate; tls.caCertificateId identifies the configured custom CA. |
| Update MQTT broker config | PUT | /orgs/{orgId}/data-bridges/mqtt-broker-configs/{mqttConfigId} | Modified | Breaking | Duplicate-name errors change from 400 to 409; renaming onto an existing configuration name is rejected. Update conflict handling. Adds tls.caCertificateId; omitting tls on PUT clears a configured custom-CA reference, so resend it when preserving TLS settings. |
| Upload MQTT CA certificate | POST | /orgs/{orgId}/data-bridges/mqtt-ca-certificates | Added | Additive | Upload one public PEM or DER CA certificate using name and certificate. Maximum certificate size is 40 KB; private keys and multi-certificate bundles are rejected. Use the returned ID as tls.caCertificateId. |
| List MQTT CA certificates | GET | /orgs/{orgId}/data-bridges/mqtt-ca-certificates | Added | Additive | List CA metadata, including certificateId, thumbprint, expiresAt, isExpired and isInUse. Certificate contents are not returned. |
| Delete MQTT CA certificate | DELETE | /orgs/{orgId}/data-bridges/mqtt-ca-certificates/{certificateId} | Added | Additive | Delete an unused CA certificate. Remove or change broker references before deleting a certificate that is in use. |
Remote Access Tunnels
The legacy creationTime sorting alias remains accepted for tunnel lists; response timestamp mappings must use the new field names.
| API Name | Method | Endpoint | Change | Impact | Details |
|---|---|---|---|---|---|
| Create tunnel session | POST | /devices/{deviceId}/tunnels/sessions | Modified | Breaking | Creating a session requires Admin permission. Request applicationPort minimum: 0 → 1. Response: creationTime → createdAt; lastModificationTime → updatedAt. Adds activeConns and the webssh service type. |
| List device tunnels | GET | /devices/{deviceId}/tunnels/sessions | Modified | Breaking | Query serviceType adds webssh; default sorting: creationTime desc → createdAt desc. Response: items[].creationTime → items[].createdAt; items[].lastModificationTime → items[].updatedAt. Items add activeConns and the webssh service type. |
| Get tunnel detail information | GET | /devices/{deviceId}/tunnels/sessions/{tunnelSessionId} | Modified | Breaking | Response: creationTime → createdAt; lastModificationTime → updatedAt. Adds activeConns and the webssh service type. A missing device returns 404 instead of 403. |
| Terminates an existing tunnel session | DELETE | /devices/{deviceId}/tunnels/sessions/{tunnelSessionId} | Modified | Breaking | Response: creationTime → createdAt; lastModificationTime → updatedAt. Adds activeConns and the webssh service type. A terminal-state conflict returns 409 instead of 400; a missing device returns 404. |
| Open a browser-based SSH session | GET | /tunnels/webssh/{tunnelSessionId} | Added | Additive | Open the browser-based SSH page using the session's returned webSsh link and the device's SSH credentials. This endpoint is outside /api/v1. |
Last updated: October 27, 2026. Release status follows the v1.2.0 Release Notes.