Skip to content

Application Developer Guide

This guide explains how to use the Coldwave Cloud Backend to build applications: dashboards, configuration UIs, mobile apps or integrations that consume device data and control devices.

It focuses on how to use the backend from an application point of view. For the full list of endpoints and events, refer to the module reference in the sidebar of the official documentation.

Who this guide is for

This document is intended for:

  • Frontend and full-stack developers building web or mobile user interfaces.
  • System integrators who want to connect existing applications to Coldwave.
  • Backend developers who need to consume Coldwave data or trigger actions.

You should be familiar with basic web technologies (HTTP, JSON, WebSockets) and have access to a running Coldwave backend instance (<<URL>>) provided by your organization or OEM.

What you can build with the Coldwave backend

Typical applications based on the Coldwave backend include:

  • Monitoring dashboards

    • Show current values and status of devices (temperature, mode, alarms, etc.).
    • Display metadata such as location, installation info, customer labels.
  • Configuration and commissioning tools

    • Configure device properties (setpoints, operating modes, schedules).
    • Attach metadata (names, locations, tags) to devices.
  • Operations & maintenance tools

    • Track alarms and events.
    • Add notes for devices (e.g. service logs, technician comments).
    • Manage firmware updates (OTA).
  • Integrations

    • Forward data or events to 3rd-party tools (Slack, voice assistants, custom backends).
    • Implement your own services on top of the Coldwave data model.

The rest of this guide shows you how to access the required data and features in a consistent way.

Core concepts in one picture

The Coldwave backend models the world in a few core entities:

  • Device
    Represents a physical (or virtual) IoT device. A device:

    • Has a unique device identifier (string).
    • Is the container for services and metadata.
    • Must expose a built-in device-service to be allowed to connect (internal, not part of the public API).
  • Service
    A service is an object exposed by a device and is identified by a service identifier (UUID v4).
    Examples:

    • A “temperature” service with temperature, humidity, battery level.
    • A “lift control” service with mode, door state, error code.
  • Property
    The smallest unit of data. A property:

    • Belongs to exactly one service on exactly one device.
    • Has a type (e.g. INT32, FLOAT, BOOL, STRING, …).
    • Has a numeric property identifier (UINT16, e.g. 0x2000 / 8192).
    • May be read-only or writable.
  • Schema
    The schema describes how a service should look from the application’s point of view:

    • Human-readable names (temperature), units (°C, %), descriptions.
    • Read-only / writable flags.
    • Enum definitions (e.g. 1 = off, 2 = silent, 3 = running).

    The schema is maintained in the backend and is not enforced on the physical device. This allows you to:

    • Map numeric property IDs to meaningful labels.
    • Change labels, units or enums without touching device firmware.
  • Meta data
    The meta module stores information that is related to the device as a whole, not to a specific service/property:

    • Human-readable device name.
    • Location, installation info, notes for operations.
    • Any additional key/value data you want to attach.
  • Events (WebSocket)
    State changes are pushed as events over a WebSocket connection:

    • Property value changes.
    • New alarms.
    • Notes added or updated. Each event has a type field and additional data, and can only be received if the current user has sufficient access rights.

Understanding these concepts is enough to read and reason about the rest of this guide.

Typical application flow

Most applications follow a similar high-level flow:

  1. Authenticate and obtain a token

    • An administrator creates a user for you in the IAM module and gives you name and code.
    • You call the signup endpoint with your chosen password.
    • You log in with username and password and obtain a JWT token via the IAM token endpoint.
  2. Discover devices and services

    • Use the service endpoints (/api/v1/devices or /api/v1/services) with depth=2 to retrieve devices, their services and properties.
    • Typically you request raw=true and map property IDs to labels yourself using the schema (see next step).
  3. Load schemas

    • Use the schema endpoints (/api/v1/schemas?depth=1) to fetch schema definitions for all services you are interested in.
    • Build a local mapping from (serviceIdentifier, propertyId) to a richer description (name, unit, enum, read-only, etc.).
  4. Load metadata

    • Use the meta endpoints to fetch metadata for devices (names, locations, tags, etc.) and show this in your UI.
  5. Open a WebSocket

    • Request a WebSocket ticket from /api/v1/events/ticket using your Bearer token.
    • Establish a WebSocket connection with the ticket and start listening for events (property changes, notes, alarms, …).
  6. Update your UI reactively

    • On startup, initialize UI state from the HTTP responses (services, schemas, meta).
    • Then apply incoming WebSocket events on top of that state.
    • Write operations (e.g. changing a setpoint, adding a note) are performed via the corresponding HTTP endpoints of the relevant module.

The rest of this guide will walk through these steps in more detail and show concrete examples.

Quickstart: From zero to first values

This chapter shows a minimal “happy path” from “I have a Coldwave backend URL” to “I see my first device values in a simple application”.

1. Prerequisites

You need:

  • A running Coldwave backend instance, e.g. https://<<URL>>.
  • A user account created by an administrator in the IAM module.
  • A set of devices already connected to the backend (for testing or production).

We will use plain curl for examples, but you can use any HTTP client or language.

2. Sign up with your user code

After an administrator created a user, you receive:

  • <<USERNAME>>
  • <<CODE>> (signup code with an expiration date)

Call the signup endpoint once, providing your own password:

bash
curl --location '<<URL>>/api/v1/iam/signup'       --header 'Content-Type: application/json'       --data '{
    "name": "<<USERNAME>>",
    "code": "<<CODE>>",
    "password": "<<PASSWORD>>"
  }'

If the request succeeds, your user is registered. You will not use the code again.

3. Obtain an access token

To access any protected endpoint you need a Bearer token. Obtain it via the IAM token endpoint using HTTP Basic auth:

bash
# USERNAME:PASSWORD base64-encoded
AUTH_HEADER="Basic $(printf '%s:%s' "<<USERNAME>>" "<<PASSWORD>>" | base64)"

curl --location '<<URL>>/api/v1/iam/token'       --header "Authorization: ${AUTH_HEADER}"

The response looks like:

json
{
  "token": "eyJhbGciOiJSUzI1NiIs..."
}

Store this string and use it as a Bearer token:

bash
TOKEN="eyJhbGciOiJSUzI1NiIs..."   # from response
AUTH="Authorization: Bearer ${TOKEN}"

4. List devices and services

To get a first impression of the data available in your instance, request all devices including their services and properties:

bash
curl --location '<<URL>>/api/v1/devices?depth=2&raw=true'       --header "${AUTH}"

or grouped by services:

bash
curl --location '<<URL>>/api/v1/services?depth=2&raw=true'       --header "${AUTH}"
  • depth=2 expands nested information in a single response.
  • raw=true returns property identifiers and values as the device exposes them.
    You will interpret them using the schemas in the next step.

At this point you can already display:

  • A list of devices.
  • For each device, a list of services.
  • For each service, a list of properties with raw IDs and types.

5. Load schemas for human-readable labels

Fetch all schemas:

bash
curl --location '<<URL>>/api/v1/schemas?depth=1'       --header "${AUTH}"

The response contains an array of schema objects similar to:

json
[
  {
    "serviceIdentifier": "00000000-0000-0000-0000-000000000000",
    "schema": {
      "name": "Example",
      "description": "Schema for an example service",
      "properties": {
        "0x2000": {
          "name": "mode",
          "description": "The mode of the example service",
          "type": "uint8",
          "enum": {
            "1": { "name": "off" },
            "2": { "name": "silent" },
            "3": { "name": "running" }
          }
        },
        "0x2001": {
          "name": "humidity",
          "description": "The humidity of the example service",
          "type": "float",
          "unit": "%",
          "readonly": true
        }
      }
    }
  }
]

Combine this with the service response to:

  • Show mode instead of 0x2000 / 8192.
  • Render a dropdown with enum names (off, silent, running) instead of a numeric input.
  • Show unit labels such as % for humidity.
  • Disable editing of properties marked as readonly.

TIP

Schema property IDs are in hexadecimal notation ("0x2000"), while the service API often uses decimal property IDs (8192). Always parse both as integers before comparing them.

6. Load metadata for nicer device lists

Use the meta endpoint to fetch device metadata, such as names and locations:

bash
curl --location '<<URL>>/api/v1/meta?depth=1'       --header "${AUTH}"

Attach this information to your device list to show user-friendly labels like:

  • “Rooftop HVAC 1 – Berlin”
  • “Lift A – Building 3 – 4th floor”

instead of plain device identifiers.

7. Open a WebSocket and listen for updates

To keep your application in sync without polling:

  1. Request a WebSocket ticket:

    bash
    curl --location '<<URL>>/api/v1/events/ticket'           --header "${AUTH}"
  2. Use this ticket to open a WebSocket connection (example in Node.js):

    ts
    import { WebSocket } from 'ws';
    
    const URL = '<<URL>>';
    const ticket = '<<TICKET>>'; // from /events/ticket
    
    const ws = new WebSocket(`wss://${URL}/api/v1/events?ticket=${ticket}`);
    
    ws.on('open', () => {
      console.log('WebSocket connected');
    });
    
    ws.on('message', (data) => {
      const event = JSON.parse(data.toString());
      console.log('Event:', event.type, event);
      // update your local state based on event.type
    });

Once the WebSocket is connected:

  • Initialize your UI with the HTTP responses (services, schemas, meta).
  • Apply incoming events to keep it up-to-date (e.g. property value changed, note added).

Using schema names in URLs

When a service has a schema defined, some endpoints allow you to use human-readable names from the schema instead of numeric identifiers in the URL or parameters.

A typical example is the open property endpoints:

text
GET /api/v1/services/:serviceIdentifier/devices/:deviceIdentifier/openProperty/:property
GET /api/v1/devices/:deviceIdentifier/services/:serviceIdentifier/openProperty/:property

For the :property URL parameter you can use either:

  • the numeric identifier in the 0x0000.TYPE form (e.g. 0x2000.UINT8), or
  • the property name as defined in the schema (e.g. mode or temperature).

This is very convenient for end-user-facing URLs or tools:

  • Your URLs become self-describing (.../openProperty/temperature instead of .../openProperty/0x2001.FLOAT).
  • You avoid hard-coding internal numeric IDs into your UI code.

Important: schema-based URLs are semantic sugar.

  • If you rename a property in the schema, any URL that uses the old name will stop working.
  • If you move or delete properties in the schema, your UI might see 404 / validation errors until it is updated.

Recommended pattern:

  • For user-facing applications and tools, it is fine to use property names in URLs.
  • For long-lived integrations or 3rd-party APIs that you do not fully control, prefer the numeric identifiers (propId and service UUIDs) to avoid breaking changes.

Next steps in this guide

Follow-up chapters can cover:

  • How to structure a frontend state model (devices, services, properties, schemas).
  • How to write values back (service API).
  • How to work with specific modules from an application perspective:
    • Notes (add / list / display notes along with device data).
    • Alarms (show active alarms, acknowledge, history).
    • OTA (show firmware version, start an update, track status).
    • Streams / Timestream (historical data & trends).
  • Access control patterns with IAM (multi-tenant UI, customer portals).