Quickstart
First steps with the nomos system Controller API, in JavaScript and with curl
This example logs in to the controller, reads all components, switches one component on and off again, follows the change and executes a scene. First in JavaScript over Socket.io, then the same steps with curl over HTTP.
A regular user may use every call in this example as well (see Permissions).
What you need
- the address of the controller on the local network, here
<controller-ip> - a user, here
USERNAMEandPASSWORD - the CID of a component that is safe to switch, such as a light. Data Model explains how to find the CID. The example uses
C5. - optionally the ID of a scene you want to execute
JavaScript (Socket.io)
You need Node.js 18 or later and socket.io-client 4.6 or later:
mkdir nomos-quickstart && cd nomos-quickstart
npm init -y
npm install socket.io-client@4Save the program as quickstart.js:
// quickstart.js - Node.js 18 or later, npm install socket.io-client@4
const { io } = require('socket.io-client');
const HOST = process.env.NOMOS_HOST; // address of the controller, e.g. 192.168.1.10
const USERNAME = process.env.NOMOS_USER;
const PASSWORD = process.env.NOMOS_PASSWORD;
const CID = process.env.NOMOS_CID; // component to switch, e.g. C5
const SCENE_ID = process.env.NOMOS_SCENE; // optional: scene to execute
const socket = io(`http://${HOST}/api/v1`, { path: '/socket.io-v4' });
// Sends an event and waits for the controller's answer
const call = (event, params = {}) => socket.timeout(15000).emitWithAck(event, params);
const sleep = (ms) => new Promise((resolve) => setTimeout(resolve, ms));
// Live values: an array of {cid, property, value, content, unit}
socket.on('onComponentUpdate', (updates) => {
for (const update of updates) {
if (update.cid === CID) console.log('onComponentUpdate:', update);
}
});
// The controller asks for a login on every new connection. Only then is auth accepted.
socket.on('stateChange', async (state) => {
if (state.part !== 'app' || state.state !== 'User Authorization needed') return;
try {
// 1. Log in, then initialise the connection
const auth = await call('auth', { username: USERNAME, password: PASSWORD });
if (auth.errorCode) throw new Error(`auth: ${auth.errorCode} ${auth.errorText}`);
await call('init', { language: 'en', appName: 'quickstart' });
// 2. Read all components
const components = await call('getAllComponents', { withProperties: false, withMappings: false });
for (const c of components) console.log(c.cid, c.name, c.category);
// 3. Switch a component on and off again
console.log('on:', await call('componentUpdate', { cid: CID, property: 'state', value: true }));
await sleep(3000);
console.log('off:', await call('componentUpdate', { cid: CID, property: 'state', value: false }));
await sleep(3000);
// 4. Execute a scene
if (SCENE_ID) console.log('scene:', await call('executeScene', { id: Number(SCENE_ID) }));
} catch (err) {
console.error(err.message);
} finally {
socket.close();
}
});
socket.on('connect_error', (err) => console.error('connect_error:', err.message));Run it with your details:
NOMOS_HOST=<controller-ip> NOMOS_USER=USERNAME NOMOS_PASSWORD=PASSWORD NOMOS_CID=C5 node quickstart.jsThe output looks roughly like this (shortened):
native_scene Scenes Automation
...
C5 Switch Switches
C6 Dimmer Lighting
C7 Temperatur Sensors
...
on: { C5: true }
onComponentUpdate: { cid: 'C5', property: 'state', content: 1, value: true }
off: { C5: true }
onComponentUpdate: { cid: 'C5', property: 'state', content: 0, value: false }The steps in detail
- Log in:
stateChangewithUser Authorization neededis followed byauthandinit. Why the program waits forstateChangeis explained under Connect and Authenticate. - Read components:
getAllComponentsreturns every component the user may see. WithwithProperties: falseandwithMappings: falsethe answer only holds master data and current values, without the description of the properties. The Data Model explains how a component is structured. - Switch:
componentUpdatesets a property. The answer holdstrueper CID if the controller accepted the command, andfalseif not, for example for an unknown CID or a missing permission.truedoes not yet mean the device has switched. - Follow changes: What the device actually reports arrives as
onComponentUpdate. The event carries a list of changes and arrives for every component the user may see, so the program filters by CID. - Execute a scene:
executeScenewith the ID fromgetScenes. The answertrueonly arrives once the scene has run completely. For an unknown ID the controller answers{errorCode: 112, errorText: 'Not found'}. Error 116 (timeout) means the confirmation did not arrive, not that the scene did not start.
On failure every call answers with errorCode and errorText. Decide in your code by errorCode; errorText is meant for people and translated into the language from init. The list of error codes is on apidocs.
HTTP (curl)
The same calls are available over HTTP, only without events. All details are under HTTP API.
1. Log in and get a session ID
curl -s -X POST -H "auth-username: USERNAME" -H "auth-password: PASSWORD" \
http://<controller-ip>/api/v1/auth{"sessionID":"<session-id>","userID":<user-id>}userID is the ID of your user. The following calls send the session ID in the header x-nomos-sid.
2. Read components
curl -s -X POST -H "x-nomos-sid: <session-id>" -H "content-type: application/json" \
-d '{"withProperties":false,"withMappings":false}' \
http://<controller-ip>/api/v1/getAllComponents[ ...,
{"cid":"C5","name":"Switch","category":"Switches","type":"Switch",
"data":[{"value":false,"content":0,"lastUpdate":"2026-10-08T12:48:28.130Z","property":"state"}, ...],
"rooms":[17], ...},
... ]3. Switch
curl -s -X POST -H "x-nomos-sid: <session-id>" -H "content-type: application/json" \
-d '{"cid":"C5","property":"state","value":true}' \
http://<controller-ip>/api/v1/componentUpdate{"C5":true}4. Query the value
Without events you query the value with getComponentData:
curl -s -X POST -H "x-nomos-sid: <session-id>" -H "content-type: application/json" \
-d '{"cid":"C5","property":"state"}' \
http://<controller-ip>/api/v1/getComponentData{"value":true,"content":1,"lastUpdate":"2026-10-08T12:49:05.877Z"}Then switch off again with "value":false.
5. Execute a scene
curl -s -X POST -H "x-nomos-sid: <session-id>" -H "content-type: application/json" \
-d '{"id":4}' \
http://<controller-ip>/api/v1/executeSceneThe answer is true once the scene has run.
6. Log out
curl -s -X POST -H "x-nomos-sid: <session-id>" http://<controller-ip>/api/v1/logouttrueThe session ID is invalid afterwards.
Where to go next
- Connect and Authenticate: HTTPS, sessions and permissions
- Data Model: what a component contains and which properties there are
- API reference: every call and event