Skip to content

Show Cameras in Your App

Put Rhombus camera thumbnails and live video in your own web or mobile app: list cameras on your server, mint short-lived federated tokens for each viewer, load snapshots, and play live video with the React SDK or an HLS player.

On this page

This guide adds a camera wall to your application: a grid of current thumbnails, and live video when a user opens a camera. Your API key never leaves your server; the browser or app gets short-lived federated tokens limited to the cameras you choose.

Loading diagram…

1. List cameras on your server

Call getMinimalCameraStateList with your API key. Keep uuid, name, locationUuid, mediaRegion and connectionStatus for each camera, then filter the list by your own rules before you return it: your users aren't Rhombus users, so only your backend knows which cameras each of them may see.

Use a key whose role covers only the locations your app serves, with live-only or read-only device access; every token you mint inherits it (Permissions).

2. Mint a token per viewer and camera

When a user opens a camera, your backend checks that they may see it and mints a token scoped to that camera with generateFederatedSessionToken:

Node.js (Express)javascript
// Your web app's exact origin. Leave domain out for native apps (see below).
const APP_ORIGIN = "https://app.example.com";

app.post("/api/cameras/:uuid/token", requireUser, async (req, res) => {
  if (!userCanSeeCamera(req.user, req.params.uuid)) return res.sendStatus(403);
  const r = await fetch("https://api2.rhombussystems.com/api/org/generateFederatedSessionToken", {
    method: "POST",
    headers: {
      "x-auth-scheme": "api-token",
      "x-auth-apikey": process.env.RHOMBUS_API_KEY,
      "Content-Type": "application/json",
    },
    body: JSON.stringify({ durationSec: 900, deviceUUid: req.params.uuid, domain: APP_ORIGIN }),
  });
  if (!r.ok) return res.sendStatus(502);
  const { federatedSessionToken, expiresAtMs } = await r.json();
  // Remember the token so it can be revoked when the user signs out (step 5)
  (req.session.rhombusTokens ??= []).push(federatedSessionToken);
  res.json({ token: federatedSessionToken, expiresAtMs });
});

Keep tokens short (minutes, not days; never more than 24 hours), scoped with deviceUUid, and renew them before the expiresAtMs in the mint response.

For a web app, set domain to your app's exact origin, an absolute origin such as https://app.example.com. Rhombus then accepts the token only on requests whose Origin (or, when there's none, Referer) is that origin, and answers any other with 403 DOMAIN_NOT_ALLOWED, so a token copied out of your page doesn't work elsewhere. Image requests carry no Origin, so they rely on the Referer: don't set Referrer-Policy: no-referrer on pages that show camera images. Leave domain out for native mobile apps, which send neither header. The domain field has the details.

3. Show thumbnails

A camera's latest snapshot is a plain image URL, so an <img> tag can load it with the token in the query string:

html
<img
  alt="Loading dock"
  src="https://media.rhombussystems.com/media/CAMERA_UUID/MEDIA_REGION/snapshot.jpeg?x-auth-scheme=federated-token&x-auth-ft=TOKEN"
/>

MEDIA_REGION is the camera's mediaRegion from step 1. Refresh thumbnails every few seconds at most, and only for cameras on screen. A grid of many cameras can mint one token per camera, or a single token without deviceUUid that covers every camera the key's role can see; the per-camera token limits what a leaked token exposes.

4. Play live video

Pick the player that fits your app:

AppPlayerGuide
React web appThe Rhombus React SDK: give it a function that fetches a token from your backend, and it renews tokens itselfReact SDK
Other web apphls.js, or Safari's native player, on wanLiveM3u8Uri with the token appendedMedia and streams: HLS
Native iOS or AndroidAVPlayer or ExoPlayer on the same HLS URLMedia and streams

Your backend gets the stream URLs from getMediaUris for the camera and passes them to the app along with the token. Recorded video uses the same URLs with a start time and duration; see Streaming video.

5. Revoke tokens when the user signs out

A token stops working at its expiresAtMs, or sooner if you revoke it or delete the API key that minted it. When a user signs out of your app, revoke the tokens you minted for their session with POST /api/org/revokeFederatedSessionToken. It takes effect within 60 seconds, an open live-video socket that uses the token closes with code 1008, and the call returns 200 whether or not the token still existed:

Node.js (Express)javascript
app.post("/logout", requireUser, async (req, res) => {
  for (const token of req.session.rhombusTokens ?? []) {
    await fetch("https://api2.rhombussystems.com/api/org/revokeFederatedSessionToken", {
      method: "POST",
      headers: {
        "x-auth-scheme": "api-token",
        "x-auth-apikey": process.env.RHOMBUS_API_KEY,
        "Content-Type": "application/json",
      },
      body: JSON.stringify({ federatedSessionToken: token }),
    });
  }
  req.session.destroy(() => res.sendStatus(204));
});

The app can also revoke its own token with the same call, authenticated with that token (x-auth-scheme=federated-token&x-auth-ft=<token>).

Before you launch

  • The API key stays on your server; nothing on a user's device can mint tokens.
  • Your backend checks, for every token request, that the user may see that camera.
  • Tokens are scoped to one camera, live for minutes, and are bound to your web app's origin with domain.
  • Signing out revokes the tokens minted for that session.
  • Token-bearing URLs are kept out of logs, analytics and error reports.
  • Your app fetches a new token before expiresAtMs, and handles a 401 by fetching a new one and reloading the image or stream.