Platform Methods

Access TelemetryOS platform features including accounts, users, devices, applications, and proxy services for external content fetching.

Platform Methods

Access to accounts, users, devices, applications, and proxy services.

Overview

These methods provide access to TelemetryOS platform features and information:

  • Accounts - Current account information
  • Users - Current user information
  • Devices - Device hardware information
  • Applications - Application discovery and embedding
  • Environment - Color scheme detection and subscription

Accounts API

Access information about the current TelemetryOS account.

Import

import { accounts } from '@telemetryos/sdk';

getCurrent()

Retrieve current account information.

Signature:

async getCurrent(): Promise<CurrentAccount>

CurrentAccount Type:

type CurrentAccount = {
  id: string;
  name: string;
  industry?: string;
  country?: string;
  region?: string;
  timezone?: string;
  language?: string;
  timeFormat?: string;
  currencySymbol?: string;
}

Returns: Promise resolving to the current account

Example:

const account = await accounts().getCurrent();

Users API

Access information about the current user.

Import

import { users } from '@telemetryos/sdk';

getCurrent()

Retrieve current user information.

Signature:

async getCurrent(): Promise<CurrentUser>

CurrentUser Type:

type CurrentUser = {
  id: string;
  email: string;
  firstName: string;
  lastName: string;
  companyName: string;
  avatarUrl: string;
}

Returns: Promise resolving to the current user

Note: Only Studio has a user context — a player authenticates as a device, not
a person — so this rejects when running on a player.

Example:

const user = await users().getCurrent();

Devices API

Access device hardware information.

Import

import { devices } from '@telemetryos/sdk';

getCurrent()

Retrieve the logical device record — the admin-configured identity and context the
application is running on. This is distinct from getInformation() (the static
hardware fingerprint) and getMetrics() (live runtime telemetry); it changes when an
admin renames, moves, or retags the device.

Signature:

async getCurrent(): Promise<Device | null>

Device Type:

type Device = {
  id: string;
  name: string;
  description: string;
  assetId: string;
  location: string;
  geo: DeviceGeo | null;
  tags: string[];
  language: string;
}

type DeviceGeo = {
  latitude: number;
  longitude: number;
  timezone: string;
}

geo is null when the admin has not configured a location, rather than defaulting
to (0, 0) — which would be indistinguishable from a real location in the Gulf of
Guinea.

Returns: Promise resolving to the device, or null when there is no device context

Example:

const device = await devices().getCurrent();

subscribeCurrent()

Subscribe to changes to the device record. The handler is invoked immediately with the
current value, then again whenever it changes.

Signature:

async subscribeCurrent(handler: (device: Device | null) => void): Promise<boolean>

Example:

await devices().subscribeCurrent((device) => {
  console.log('Device is now', device?.name);
});

unsubscribeCurrent()

Signature:

async unsubscribeCurrent(handler?: (device: Device | null) => void): Promise<boolean>

Omit the handler to remove all of them.

getInformation()

Retrieve hardware information about the current device.

Signature:

async getInformation(): Promise<DeviceInformation>

DeviceInformation Type:

type DeviceInformation = {
  serialNumber: string;
  model: string;
  manufacturer: string;
  platform: string;
}

Returns: Promise resolving to device information

Example:

const info = await devices().getInformation();

Note: Only available on physical devices (not in admin portal)

getMetrics()

Retrieve live runtime telemetry for the device. These values change continuously —
prefer subscribeMetrics() over polling this in a loop.

Signature:

async getMetrics(): Promise<DeviceMetrics | null>

DeviceMetrics Type:

type DeviceMetrics = {
  cpuLoadPercent: number;
  memoryUsedPercent: number;
  cacheUsagePercent: number;
  uptimePercent: number;
}

Example:

const metrics = await devices().getMetrics();

subscribeMetrics()

Signature:

async subscribeMetrics(handler: (metrics: DeviceMetrics | null) => void): Promise<boolean>

unsubscribeMetrics()

Signature:

async unsubscribeMetrics(handler?: (metrics: DeviceMetrics | null) => void): Promise<boolean>

getCapabilities()

Retrieve what hardware and software features the device supports, so an application can
enable features conditionally.

Signature:

async getCapabilities(): Promise<DeviceCapability[] | null>

DeviceCapability Type:

type DeviceCapability =
  | 'configurableDisplays'
  | 'configurableAudio'
  | 'applicationContainers'
  | 'applicationManagement'
  | 'resourceCaching'
  | 'bluetooth'
  | 'wiFi'
  | 'ethernet'
  | 'usbProvisioning'
  | 'videoStreaming'
  | 'screenCaptureStreaming'
  | 'mqtt'
  | 'onScreenKeyboard'

The same list is exported as a runtime array, deviceCapabilities, for validation.

Returns: Promise resolving to the capability list, null when there is no device
context, or an empty array when the device is known but exposes none

Example:

const capabilities = await devices().getCapabilities();
if (capabilities?.includes('mqtt')) {
  // Safe to use the MQTT API
}

getRootApplicationSpecifier()

Retrieve the application specifier of the root application hosting this one — for
example the layout or playlist renderer it is embedded under.

Signature:

async getRootApplicationSpecifier(): Promise<string | null>

Returns: Promise resolving to the specifier, or null when there is no root
application context

Example:

const root = await devices().getRootApplicationSpecifier();

Applications API

Discover and embed other TelemetryOS applications.

Import

import { applications } from '@telemetryos/sdk';

getAllByMountPoint()

Find all applications with a specific mount point.

Signature:

async getAllByMountPoint(mountPoint: string): Promise<Application[]>

Application Type:

type Application = {
  name: string;
  mountPoints: Record<string, MountPoint>;
}

type MountPoint = {
  path: string;
  [key: string]: any;
}

Parameters:

  • mountPoint - Mount point identifier to search for

Returns: Array of applications with that mount point

Example:

const widgets = await applications().getAllByMountPoint('dashboard-widget');

getByName()

Find a specific application by name.

Signature:

async getByName(name: string): Promise<Application | null>

Parameters:

  • name - Application name

Returns: Application object or null if not found

Example:

const weatherApp = await applications().getByName('weather-widget');

setDependencies()

Declare application dependencies for preloading.

Signature:

async setDependencies(applicationSpecifiers: string[]): Promise<{
  ready: string[];
  unavailable: string[];
}>

Parameters:

  • applicationSpecifiers - Array of application specifier strings

Returns: Object with ready and unavailable arrays

Example:

const result = await applications().setDependencies([
  'weather-widget-hash123',
  'news-ticker-hash456'
]);

Important: Call and await setDependencies() before loading sub-applications in iframes.

Environment API

Access environment settings including color scheme preferences, online status, and the runtime host the application is running in.

Import

import { environment } from '@telemetryos/sdk';

ColorScheme Type

type ColorScheme = 'light' | 'dark' | 'system'

EnvironmentType Type

The runtime host an application is running in.

type EnvironmentType = 'studio' | 'player' | 'web' | 'companion' | 'development'

getColorScheme()

Retrieve the current color scheme setting.

Signature:

async getColorScheme(): Promise<ColorScheme>

Returns: Promise resolving to the current color scheme

Example:

const colorScheme = await environment().getColorScheme();

subscribeColorScheme()

Subscribe to color scheme changes.

Signature:

async subscribeColorScheme(handler: (colorScheme: ColorScheme) => void): Promise<boolean>

Parameters:

  • handler - Callback function invoked when the color scheme changes

Returns: Promise resolving to true if subscription was successful

Example:

await environment().subscribeColorScheme((colorScheme) => {
  console.log('Color scheme changed:', colorScheme);
});

unsubscribeColorScheme()

Unsubscribe from color scheme changes.

Signature:

async unsubscribeColorScheme(handler?: (colorScheme: ColorScheme) => void): Promise<boolean>

Parameters:

  • handler - Optional. The specific handler to remove. If omitted, all handlers are removed.

Returns: Promise resolving to true if unsubscription was successful

Example:

await environment().unsubscribeColorScheme();

getCurrent()

Retrieve the runtime host the application is running in. Useful for adapting behavior per host — for example, showing different UI in Studio versus on a Player, or enabling dev-only tooling.

Signature:

async getCurrent(): Promise<EnvironmentType>

Returns: Promise resolving to the current EnvironmentType

Example:

const env = await environment().getCurrent();
if (env === 'player') {
  // Running on a digital signage player
}

getIsOnline()

Retrieve whether the application currently has network connectivity.

Signature:

async getIsOnline(): Promise<boolean>

Returns: Promise resolving to true when online, false when offline

Example:

const isOnline = await environment().getIsOnline();

subscribeIsOnline()

Subscribe to online/offline status changes. The handler is invoked immediately with the current value, then again whenever connectivity changes — letting an app react when it comes back online (for example, reloading APIs or media).

Signature:

async subscribeIsOnline(handler: (isOnline: boolean) => void): Promise<boolean>

Parameters:

  • handler - Callback function invoked with the online status, and again on every change

Returns: Promise resolving to true if subscription was successful

Example:

await environment().subscribeIsOnline((isOnline) => {
  if (isOnline) {
    // Back online — refresh data
  }
});

unsubscribeIsOnline()

Unsubscribe from online/offline status changes.

Signature:

async unsubscribeIsOnline(handler?: (isOnline: boolean) => void): Promise<boolean>

Parameters:

  • handler - Optional. The specific handler to remove. If omitted, all handlers are removed.

Returns: Promise resolving to true if unsubscription was successful

Example:

await environment().unsubscribeIsOnline();

getDisplayProperties()

Retrieve the properties of the display the application is rendered on, including its
overall size in pixels across every screen.

Signature:

async getDisplayProperties(): Promise<DisplayProperties>

DisplayProperties Type:

type DisplayProperties = {
  /** Overall display width in pixels, spanning all screens. */
  width: number
  /** Overall display height in pixels, spanning all screens. */
  height: number
}

The type is intentionally extensible — future fields such as per-screen geometry,
orientation, or device pixel ratio may be added without a breaking change, so treat
unknown fields as optional.

Example:

const { width, height } = await environment().getDisplayProperties();

Availability: currently served only when your application runs inside a root
application that provides it (the layout renderer). Elsewhere nothing answers the
request, so it rejects after the SDK's 30-second timeout — catch it and fall back
rather than blocking your render path on the result.

subscribeDisplayProperties()

Subscribe to display-property changes. The handler is invoked immediately with the
current value, then again whenever it changes.

Signature:

async subscribeDisplayProperties(handler: (properties: DisplayProperties) => void): Promise<boolean>

Example:

await environment().subscribeDisplayProperties(({ width, height }) => {
  console.log(`Display is now ${width}x${height}`);
});

unsubscribeDisplayProperties()

Signature:

async unsubscribeDisplayProperties(handler?: (properties: DisplayProperties) => void): Promise<boolean>

Omit the handler to remove all of them.

setRootSettingsNavigation()

Register navigation entries for a root application in the TelemetryOS Studio UI sidebar. Your entries are merged into Studio's built-in navigation, letting you surface your own management screens (for example "Canvases" or "Channels") alongside the built-in ones.

⚙️

This is a root-application, worker-only API. Call it from a background worker — mount-point contexts (render/settings) are transient iframes, so the worker is the single stable place to own the nav definition. Calling it from a mount point throws. It is fire-and-forget (returns void), so do not await it. Root applications import environment from @telemetryos/root-sdk (also re-exported from @telemetryos/sdk).

Signature:

setRootSettingsNavigation(navigation: RootSettingsNavigationOpts): void

Payload types:

type RootSettingsNavigationOpts = {
  sections: NavEntry[]
}

type NavEntry = {
  key: string                // camelCase id, unique among its siblings
  title?: string             // display label (omit on reference-only entries)
  icon?: NavEntryIcon
  path?: string              // sub-path within your rootSettings mount point
  url?: string               // absolute external link (opens in a new tab); path wins if both set
  permissions?: string[]     // user needs at least one; empty/undefined = no gate
  before?: string | string[] // position before a sibling key (first match wins)
  after?: string | string[]  // position after a sibling key (wins over `before`)
  items?: NavEntry[]         // children (recursive)
}

type NavEntryIcon = {
  name?: string              // one of Studio's curated icon keys (see below)
  svg?: string               // raw SVG (DOMPurify-sanitized); use currentColor
}

Parameters:

  • navigation - The sidebar sections to contribute. sections may reference built-in sections by key (to nest items into them) and/or declare new top-level sections.

Returns: void (fire-and-forget; do not await)

Example — nest an item under a built-in section:

import { environment } from '@telemetryos/root-sdk';

// Runs in a background worker (e.g. src/background-worker.ts)
environment().setRootSettingsNavigation({
  sections: [
    {
      key: 'content', // built-in Studio section
      items: [
        { key: 'canvases', title: 'Canvases', icon: { name: 'image' }, path: '/', after: 'media' },
      ],
    },
  ],
});

Example — a full navigation tree (multiple sections):

Imagine a root application that manages self-service ordering across a restaurant chain — menus, restaurants and their kiosks, and orders. It contributes three top-level sections (each anchored after the relevant built-in one) with eight screens between them:

environment().setRootSettingsNavigation({
  sections: [
    {
      key: 'menu',
      title: 'Menu',
      after: 'content', // place this section after the built-in Content section
      items: [
        { key: 'menuBoards', title: 'Menu Boards', icon: { name: 'grid' }, path: '/menu/boards' },
        { key: 'menuItems', title: 'Items & Pricing', icon: { name: 'book' }, path: '/menu/items' },
        {
          key: 'dayparts',
          title: 'Dayparts',
          // No clock in the curated icon set — use a custom SVG (currentColor so it themes)
          icon: {
            svg: '<svg viewBox="0 0 24 24"><circle cx="12" cy="12" r="9" fill="none" stroke="currentColor" stroke-width="2"/><path d="M12 7v5l3 2" fill="none" stroke="currentColor" stroke-width="2"/></svg>',
          },
          path: '/menu/dayparts',
        },
      ],
    },
    {
      key: 'restaurants',
      title: 'Restaurants',
      after: 'devices',
      items: [
        { key: 'locations', title: 'Locations', icon: { name: 'map' }, path: '/restaurants/locations' },
        { key: 'kiosks', title: 'Kiosks', icon: { name: 'devices' }, path: '/restaurants/kiosks' },
      ],
    },
    {
      key: 'orders',
      title: 'Orders',
      after: 'data',
      items: [
        { key: 'liveOrders', title: 'Live Orders', icon: { name: 'dashboard' }, path: '/orders/live' },
        {
          key: 'orderHistory',
          title: 'Order History',
          icon: { name: 'database' },
          path: '/orders/history',
          after: 'liveOrders', // sibling anchor within the Orders section
        },
        {
          key: 'orderReports',
          title: 'Reports',
          icon: { name: 'analytics' },
          path: '/orders/reports',
          permissions: ['orders.reports'], // hidden unless the user holds this permission
        },
      ],
    },
  ],
});

Contribution shapes:

  • Nest under a built-in section — reference the section by key and put your items in items. On a reference entry Studio keeps the section's own title/icon ("first contributor wins"), so put display fields on the child.
  • New top-level section — a top-level entry with items renders as an uppercase header plus clickable children.
  • Do not contribute a bare top-level leaf (a top-level entry with path/title but no items) — Studio renders the top level as non-clickable headers and drops childless top-level nodes, so it renders nothing.

Built-in anchor keysbefore/after (and reference entries) resolve against these current built-in keys. Anchors are sibling-scoped (a key only resolves at its own level), and these keys may change over time:

LevelKeys
Top-level sectionshome, devices, content, data, settings
Under contentplaylists, media, applications, campaigns, overrides
Under devicesdevicesIndex, devicesGrid, devicesMap, reports
Under datacampaignLogs, accountLogs, deviceLogs, playbacks
Under homedashboard

Iconsicon.name must be one of Studio's curated keys: alert, analytics, apps, book, campaign, chart, content, dashboard, database, device, devices, grid, home, image, map, media, package, playlist, playlists, settings, user, users. Unknown names render no icon. For anything else supply icon.svg with a raw SVG string (DOMPurify-sanitized; use currentColor so it follows Studio's theme).

See Background Workers for how to declare and build a worker, and the Settings mount point for related per-instance configuration.

Next Steps


What’s Next

Did this page help you?