The SDK for connected experiences

Build apps that work together in real time.

Shared workspaces. Live conversations. Connected devices. Bring them together with messaging, presence, WebRTC and channel storage.

Explore the apps

Free during beta No credit card Open-source SDKs

Whiteboard / shared workspaceBuilt with the SDK
Whiteboard demo workspace with a populated collaborative board and drawing tools
Demo workspace — sample dataOpen Whiteboard Full-size image

One shared channel. Every participant in the loop.

This is the SDK running on this page — a real channel, a temporary key from this site's own server.
Your stack. Your interface.JavaScriptJavaPythonC++ experimentalMeet the SDK

Small pieces. Shared possibilities.

Four primitives, one connection.

Compose what your app needs without building a separate connection for every feature.

01

Channels & messaging

Broadcast to a room, address one client, or filter delivery. Use ephemeral messages for fast-changing state.

WebSocket + HTTP fallback
02

Presence

Know who is connected. Build participant lists, live cursors and join or leave notifications.

Peers + connection events
03

WebRTC signaling & P2P

Set up peer connections for calls and data, with hosted TURN/STUN relay support when a direct path is unavailable.

Media + data channels
04

Channel storage

Save shared state in a per-channel key-value store so the next participant can pick up where you left off.

JavaScript today · other clients in progress

Your clients, one shared channel. JavaScript, Java, Python and C++ clients talk to one managed service — channels, presence, storage, signaling — and WebRTC media goes peer to peer with relay fallback.Explore the architecture

Built with the SDK

See what one connection can do.

These are working applications, built on the same primitives you can use in your own product.

Explore all SDK demos
Whiteboard

Draw and share a live canvas.

About Whiteboard
Real-time chat

Messages and presence in one channel.

Drop

A focused peer-to-peer file demo.

Evidence Chain

Append a record that cannot be quietly rewritten.

About Evidence Chain
Dead Drop

Leave something for the next participant.

About Dead Drop
Under the Hood

Inspect the connection as it happens.

About Under the Hood
Rewind

Explore the saved versions of a board.

About Rewind
The playground

Explore games and interactive examples.

Start building

Your first
shared channel.

Connect with a room name and password. Listen for messages. Give another client the same room details and start building together.

Load the SDK: two script tags, no build stepFive-minute quickstart in four languages

Your backend uses the developer API key directly. Browser code uses a temporary key issued by that backend.

Read the complete setup guide
Script tags

Load these in order; AgentConnection is then a global. (The npm package is not published yet.)

<script src="https://hmdevonline.com/messaging-platform/sdk/generated-web-agent-js/js/web-agent.libs.js"></script>
<script src="https://hmdevonline.com/messaging-platform/sdk/generated-web-agent-js/js/web-agent.js"></script>
shared-room.js
// AgentConnection is a global once the two script tags have loaded.

const api = 'https://hmdevonline.com/messaging-platform/api/v1/messaging-service';
const agent = new AgentConnection();

agent.addEventListener('message', ({ response }) => {
  if (response.status !== 'success') return;
  for (const message of response.data || []) {
    if (message.type === 'chat-text') console.log(message.content);
  }
});
agent.addEventListener('connect', ({ response }) => {
  if (response.status === 'success') agent.sendMessage('Hello, room!');
});

agent.connect({
  api, apiKey: 'your-temporary-api-key',
  channelName: 'design-room', channelPassword: 'shared-secret',
  agentName: 'user-' + crypto.randomUUID(), autoReceive: true
});
The browser receives this temporary key from your own server. See the safe handoff.

Browser credential handoff

Your backend keeps the developer key. Your browser gets a temporary one.

Developers normally have both a frontend and backend. The backend calls the platform directly with its developer API key; it mints a temporary key only when the frontend needs its own platform connection.

Temporary keys

Issue short-lived keys from your server. Keep the long-lived developer credential out of browser bundles.

Channel isolation

Private scope separates channels by developer. Public scope lets different developers join a shared room.

Encrypted transport

TLS for API traffic, DTLS for peer connections, and channel passwords hashed before sending.

  1. 1. Your serverAuthenticates the signed-in user and calls the platform using the developer key stored in its environment.
  2. 2. Messaging PlatformIssues a short-lived, optionally single-use temporary key and returns its expiry.
  3. 3. BrowserReceives only the temporary key, opens its connection, and never stores the developer key.
server.mjs — your backend
// The developer key stays here. It may call platform APIs directly.
// This route mints a temporary key only for an authorised browser connection.
app.post('/api/messaging-access', requireSignedInUser, async (req, res) => {
  const platform = await fetch('https://hmdevonline.com/messaging-platform/api/v1/messaging-service/channels/api-access', {
    method: 'POST',
    headers: { 'Content-Type': 'application/json', 'X-API-Key': process.env.MESSAGING_PLATFORM_API_KEY },
    body: JSON.stringify({ ttlSeconds: 30, singleUse: true })
  });
  const body = await platform.json();
  const access = body.data;
  if (!platform.ok || !access?.temporaryKey) return res.status(502).json({ error: 'Could not create messaging access.' });
  res.set('Cache-Control', 'no-store');
  res.json({ temporaryKey: access.temporaryKey, expiresAt: access.expiresAt });
});
client.js — browser
const access = await fetch('/api/messaging-access', {
  method: 'POST', credentials: 'same-origin'
}).then(async response => {
  const body = await response.json();
  if (!response.ok) throw new Error(body.error || 'Access was not granted.');
  return body;
});

const agent = new AgentConnection();
agent.connect({
  api: 'https://hmdevonline.com/messaging-platform/api/v1/messaging-service',
  apiKey: access.temporaryKey,
  channelName: 'design-room', channelPassword: 'shared-secret',
  agentName: 'user-' + crypto.randomUUID(), autoReceive: true
});

Backend direct access: use the developer API key from your server environment when your backend creates channels, runs a worker, or calls a platform API itself. Do not create a temporary key for server-to-server calls. Create one only after authorising a frontend user who needs to connect from their browser.

Why use a temporary key? If a browser is compromised, the exposed key expires quickly and can be limited to one connection. Your developer key can create access for every client, so it must stay in your server environment—not in JavaScript, a mobile bundle, local storage, or a repository.

Read the complete temporary-key guide

Free during beta

Free for development, testing and prototypes. APIs may change, uptime is not guaranteed, and production workloads are not recommended today.

JavaScriptchannel storage client
ExperimentalC++ client support
App-specificfile-transfer limits and setup
No SLAuptime is not guaranteed

Make something connected

What will you build together?

Start with a key. Explore an example. Make it your own.

Read the docs