Embed live and recorded video from Rhombus cameras in your applications using HLS streams, thumbnails, and shared playback URLs delivered through the API.
All media.rhombussystems.com endpoints use the same authentication as the main API — include the x-auth-scheme and x-auth-apikey headers on every request.
To get the cameraUuid and mediaRegion for a camera, call POST /api/camera/getMinimalCameraStateList. The response contains a cameraStates array; each entry has uuid and mediaRegion fields.
# 1. List cameras to get UUIDs and media regionscurl -X POST \ "https://api2.rhombussystems.com/api/camera/getMinimalCameraStateList" \ -H "x-auth-scheme: api-token" \ -H "x-auth-apikey: YOUR_API_KEY" \ -H "Content-Type: application/json" \ --data '{}'
cURL
# 2. Fetch the thumbnail using a camera's UUID and media regioncurl -X GET \ "https://media.rhombussystems.com/media/{CAMERA_UUID}/{MEDIA_REGION}/snapshot.jpeg" \ -H "x-auth-scheme: api-token" \ -H "x-auth-apikey: YOUR_API_KEY" \ --output thumbnail.jpg
To get a JPEG image at a specific historical timestamp, call POST /api/video/getExactFrameUri. The response contains a frameUri — make a GET request to that URI with the same authentication headers to download the frame.
async function getFrameAtTime(cameraUuid, timestampMs, apiKey) { // Get a signed frame URI const frameUriResponse = await fetch('https://api2.rhombussystems.com/api/video/getExactFrameUri', { method: 'POST', headers: { 'x-auth-scheme': 'api-token', 'x-auth-apikey': apiKey, 'Content-Type': 'application/json' }, body: JSON.stringify({ cameraUuid: cameraUuid, timestampMs: timestampMs // epoch milliseconds }) }); const { frameUri } = await frameUriResponse.json(); // Fetch the actual JPEG const frameResponse = await fetch(frameUri, { headers: { 'x-auth-scheme': 'api-token', 'x-auth-apikey': apiKey } }); return frameResponse.blob();}
The request also accepts optional downscaleFactor, jpgQuality, and permyriadCropX/permyriadCropY/permyriadCropWidth/permyriadCropHeight fields (each in 1/10000ths of the image dimensions, where 10000 = 100%).
Create a shared stream, then drop the returned URL into an iframe. The iframe player handles authentication via the URL itself, so no API key is needed in the browser.
If you want to render live video in your own player rather than the hosted iframe, use sharedLiveM3U8StreamUrl from the same createSharedLiveVideoStream response. The manifest is a standard HLS .m3u8 and is signed with a token in the URL itself — no x-auth-apikey header is needed when fetching it.
The HLS URL is single-org-scoped and time-limited. Treat it as a credential and don’t expose it in public-facing pages without an expiration policy.
Safari plays HLS natively. For other browsers, use hls.js:
Because creating a shared stream requires an API key, do the createSharedLiveVideoStream call from a server you control and pass only the resulting sharedLiveM3U8StreamUrl (or sharedLiveVideoStreamUrl) to the browser. Keep the API key out of client code.
Downloading recorded footage as a single MP4 file is not exposed as a public API operation. The Rhombus storage layer serves recorded video as a sequence of media segments rather than a pre-rendered MP4, so producing a downloadable clip requires fetching and concatenating segments client-side.The supported way to do this is the Rhombus CLI:
# Download the last hour of footage from a camera as MP4rhombus footage --camera CAMERA_UUID --duration 1h --output footage.mp4# Download the clip associated with a specific alertrhombus alert download --alert ALERT_UUID --output alert.mp4
For alert-driven workflows, configure a webhook to deliver alert events to your service, then call the CLI (or replicate its segment-fetch logic) to retrieve the corresponding clip.To list recent alerts programmatically, use POST /api/event/getPolicyAlerts — the previous getPolicyAlertsV2 endpoint is deprecated.
Keep API keys server-side: Never expose x-auth-apikey in browser code. Call createSharedLiveVideoStream from your backend and pass only the resulting URLs to the client.
HTTPS only: Always use HTTPS for API calls and shared stream URLs.
Scope keys narrowly: Limit each API key to the minimum permissions required.
Set expirations on shared streams: Pass expirationTimeSecs when creating shared streams so URLs don’t outlive the use case.
<video controls aria-label={`Live feed from camera ${cameraName}`} poster={thumbnailUrl}> <track kind="captions" src="captions.vtt" srcLang="en" label="English" /> Your browser does not support the video tag.</video>