nimeet Docs
中文

Whiteboard Quickstart

Create a room, mint a room token, join from the Web SDK and draw your first stroke.

Version v1.0.0 · Updated 2026-10-28 · revision 1

This page gets a whiteboard running in four steps: create a room, mint a room token, join with the Web SDK and draw a stroke, then export a snapshot or a replay.

Prerequisites

  • A project with RTC enabled and its customerId / customerSecret (project keys page in the console).
  • The control-plane base URL (the examples use https://api.your-domain.example).
  • Node.js 22+ or any browser runtime with Fetch.

Step 1: create a room

Call the room endpoint with project credentials. limit is the maximum number of writable members; 0 means unlimited.

bash
curl --request POST "$NIMEET_API_BASE/v1/whiteboard/rooms" \
  --user "$NIMEET_CUSTOMER_ID:$NIMEET_CUSTOMER_SECRET" \
  --header "content-type: application/json" \
  --data '{"isRecord": false, "limit": 8}'

The uuid in the response identifies the room.

Step 2: mint a room token

A room token is bound to that room and carries a role and a lifetime in milliseconds (0 means no expiry). The browser should only ever receive the token, never the project secret.

bash
curl --request POST "$NIMEET_API_BASE/v1/whiteboard/tokens/rooms/$ROOM_UUID" \
  --user "$NIMEET_CUSTOMER_ID:$NIMEET_CUSTOMER_SECRET" \
  --header "content-type: application/json" \
  --data '{"role": "writer", "lifespan": 3600000}'

Step 3: join and draw

javascript
import { WhiteboardSdk } from '@nimeet/sdk-whiteboard-web';

const sdk = new WhiteboardSdk({ apiBase: 'https://api.your-domain.example' });
const room = await sdk.joinRoom({
  uuid: ROOM_UUID,
  roomToken: ROOM_TOKEN,
  memberId: 'alice',
});

await room.addPage({ name: 'page1', path: '/demo/page1' });
await room.setScenePath('/demo/page1');

const stroke = await room.drawStroke({
  appliance: 'pencil',
  color: '#1f6feb',
  width: 3,
  points: [
    { x: 120, y: 160 },
    { x: 220, y: 240 },
    { x: 320, y: 180 },
  ],
});
console.log('stroke', stroke.id, 'room version', room.roomInfo.version);

Page switching, image insertion and viewport movement use room.setScenePath, room.insertImage and room.moveCamera; undo and redo are room.undo() / room.redo().

Step 4: export and replay

bash
curl --request GET "$NIMEET_API_BASE/v1/whiteboard/rooms/$ROOM_UUID/snapshot" \
  --user "$NIMEET_CUSTOMER_ID:$NIMEET_CUSTOMER_SECRET"

curl --request GET "$NIMEET_API_BASE/v1/whiteboard/rooms/$ROOM_UUID/replay?from=2026-10-28T00:00:00Z" \
  --user "$NIMEET_CUSTOMER_ID:$NIMEET_CUSTOMER_SECRET"

The snapshot contains every scene, stroke, image and the operation log; replay returns operation frames ordered by time. You can also download <ROOM_UUID>/snapshot.svg as a thumbnail of the current scene.

Realtime sync

The Web SDK publishes operations to the whiteboard topic through an injected LiveKit transport:

javascript
import { LiveKitWhiteboardSync, WhiteboardSdk } from '@nimeet/sdk-whiteboard-web';

const sync = new LiveKitWhiteboardSync({
  publishData: (payload, options) => room.localParticipant.publishData(payload, options),
});
room.localParticipant.on('dataReceived', (packet) => sync.receive(packet.payload));

const sdk = new WhiteboardSdk({ apiBase: 'https://api.your-domain.example' });
const whiteboard = await sdk.joinRoom({ uuid: ROOM_UUID, roomToken: ROOM_TOKEN, memberId: 'alice', sync });

REST remains the authoritative state; if the realtime channel drops a packet, call room.refresh() to re-read the scene state.

Next steps

Generated by the documentation build pipeline · 2026-10-31 01:24:02 UTC · Documentation center v1.1.0.

Content follows the public API definitions.

ni-meet is a self-hosted RTC PaaS with a LiveKit-based media plane (Apache-2.0) and an Agora-compatible API.