Server SDK (Node.js)

Manage rooms, tokens, recordings, streaming, and ingress from your backend

Overview

The BaxCloud Server SDK (@baxcloud/server-sdk) is a Node.js/TypeScript library for server-side operations. Use it to create rooms, generate access tokens, manage recordings, stream to external platforms, create ingress endpoints, and verify webhooks — all from your backend server.

Room & Token Management

Create rooms, generate tokens, manage participants

Recording & Streaming

Record rooms, stream to YouTube/Twitch, auto-stream config

Webhooks

Verify webhook signatures, parse events, Express middleware

Installation

1npm install @baxcloud/server-sdk
💡

Requirements

Node.js 18+ (uses native fetch). TypeScript 5+ recommended.

Quick Start

server.ts
1import { BaxCloudClient } from '@baxcloud/server-sdk';
2
3const client = new BaxCloudClient({
4  apiKey: process.env.BAXCLOUD_API_KEY!,
5  // baseUrl: 'https://api.baxcloud.io', // default
6  // timeout: 30000, // default 30s
7});
8
9// Create a room
10const room = await client.createRoom({
11  name: 'my-meeting',
12  maxParticipants: 50,
13  enableRecording: true,
14});
15
16// Generate access token for a participant
17const { token } = await client.generateToken({
18  roomName: 'my-meeting',
19  participantIdentity: 'user-123',
20  participantName: 'John Doe',
21  ttl: 3600, // 1 hour
22  grants: {
23    canPublish: true,
24    canSubscribe: true,
25    canPublishData: true,
26  },
27});
28
29// Send token to the client
30console.log('Token:', token);

Room Management

1// Create a room
2const room = await client.createRoom({
3  name: 'team-standup',
4  maxParticipants: 20,
5  emptyTimeout: 300,    // Close after 5 min empty
6  metadata: '{"type": "standup"}',
7  enableRecording: true,
8});
9
10// List all rooms
11const rooms = await client.listRooms();
12
13// Get room details
14const roomDetails = await client.getRoom('team-standup');
15
16// Update room metadata
17await client.updateRoomMetadata('team-standup', '{"status": "active"}');
18
19// Delete a room
20await client.deleteRoom('team-standup');

Token Generation

Tokens authenticate participants when they join a room. Always generate tokens on your server — never expose your API key to the client.

1// Full-access participant (host)
2const hostToken = await client.generateToken({
3  roomName: 'my-room',
4  participantIdentity: 'host-1',
5  participantName: 'Room Host',
6  ttl: 7200,
7  grants: {
8    canPublish: true,
9    canSubscribe: true,
10    canPublishData: true,
11    canUpdateOwnMetadata: true,
12  },
13});
14
15// View-only participant (viewer)
16const viewerToken = await client.generateToken({
17  roomName: 'my-room',
18  participantIdentity: 'viewer-42',
19  participantName: 'Viewer',
20  ttl: 3600,
21  grants: {
22    canPublish: false,      // Cannot send audio/video
23    canSubscribe: true,     // Can receive audio/video
24    canPublishData: true,   // Can send chat messages
25  },
26});
⚠️

Security

Never generate tokens on the client side. Your API key must remain secret. Use an API route (Next.js, Express, etc.) to generate tokens on demand.

Participant Management

1// List participants in a room
2const participants = await client.listParticipants('my-room');
3
4for (const p of participants) {
5  console.log(`${p.name} (${p.identity}) - ${p.state}`);
6}
7
8// Remove a participant
9await client.removeParticipant('my-room', 'user-123');
10
11// Update participant metadata
12await client.updateParticipantMetadata(
13  'my-room',
14  'user-123',
15  '{"role": "moderator"}'
16);

Recording

See also: Recording Guide

1// startRecord — start cloud recording
2const recording = await client.startRecord({
3  roomName: 'my-room',
4  fileType: 'MP4',
5});
6console.log('Recording ID:', recording.id);
7console.log('Egress ID:', recording.egressId);
8
9// stopRecord — stop an active recording
10await client.stopRecord(recording.egressId);
11
12// listRecordings — list all recordings
13const { items } = await client.listRecordings({
14  status: 'completed',
15  page: 1,
16  limit: 20,
17});
18
19// listActiveRecordings — list currently running recordings
20const active = await client.listActiveRecordings('my-room');
21
22// getRecording — get recording details
23const rec = await client.getRecording(recording.id);
24
25// getRecordingDownloadUrl — get temporary download URL
26const { downloadUrl, expiresIn } = await client.getRecordingDownloadUrl(
27  recording.id,
28  3600 // expires in 1 hour
29);

Stream Out (Egress)

See also: Stream Out Guide

1// Stream to YouTube + Twitch simultaneously
2const stream = await client.startStream({
3  roomName: 'my-room',
4  mode: 'both',       // Record + Stream
5  layout: 'speaker',
6  quality: '1080p',
7  file: { fileType: 'MP4' },
8  stream: {
9    urls: [
10      'rtmp://a.rtmp.youtube.com/live2/YOUTUBE_KEY',
11      'rtmp://live.twitch.tv/app/TWITCH_KEY',
12    ],
13  },
14});
15
16// Stop streaming
17await client.stopStream(stream.id);
18
19// Configure auto-streaming
20await client.updateAutoStreamConfig({
21  enabled: true,
22  mode: 'record',
23  quality: '720p',
24  minParticipants: 2,
25});

Stream In (Ingress)

See also: Stream In Guide

1// Create RTMP ingress (for OBS Studio)
2const ingress = await client.startStreamIn({
3  inputType: 'RTMP_INPUT',
4  roomName: 'my-room',
5  participantIdentity: 'obs-streamer',
6  participantName: 'OBS Studio',
7  enableTranscoding: true,
8});
9
10console.log('RTMPS URL:', ingress.rtmpsUrl);
11console.log('Stream Key:', ingress.streamKey);
12
13// Create WHIP ingress (for browser/OBS 30+)
14const whip = await client.startStreamIn({
15  inputType: 'WHIP_INPUT',
16  roomName: 'my-room',
17  participantIdentity: 'whip-streamer',
18  bypassTranscoding: true,
19});
20
21console.log('WHIP URL:', whip.whipUrl);
22console.log('Bearer Token:', whip.token);
23
24// List ingress endpoints
25const { items } = await client.listStreamIn({ roomName: 'my-room' });
26
27// Delete ingress
28await client.stopStreamIn(ingress.id);

Webhook Verification

Verify webhook signatures to ensure events are genuinely from BaxCloud:

webhook-handler.ts
1import express from 'express';
2import { webhookMiddleware } from '@baxcloud/server-sdk';
3
4const app = express();
5
6// Use the middleware — it verifies the signature and parses the event
7app.post('/webhooks/baxcloud',
8  express.raw({ type: 'application/json' }),
9  webhookMiddleware({
10    webhookSecret: process.env.BAXCLOUD_WEBHOOK_SECRET!,
11  }),
12  (req, res) => {
13    const event = req.body; // Parsed & verified event
14
15    switch (event.event) {
16      case 'room.started':
17        console.log('Room started:', event.data.roomName);
18        break;
19      case 'participant.joined':
20        console.log('Participant joined:', event.data.identity);
21        break;
22      case 'egress.ended':
23        console.log('Recording completed:', event.data.egressId);
24        break;
25    }
26
27    res.json({ received: true });
28  }
29);

Complete Method Reference

CategoryMethodDescription
Rooms
RoomscreateRoom(options)Create a new room
RoomsgetRoom(name)Get room details
RoomslistRooms()List all rooms
RoomsdeleteRoom(name)Delete a room
RoomsupdateRoomMetadata(name, metadata)Update room metadata
Tokens
TokensgenerateToken(options)Generate participant access token
Participants
ParticipantslistParticipants(roomName)List participants in a room
ParticipantsremoveParticipant(room, identity)Kick a participant
ParticipantsupdateParticipantMetadata(...)Update participant metadata
Recording
RecordingstartRecord(roomName, options?)Start cloud recording for a room
RecordingstopRecord(egressId)Stop an active recording
RecordinglistRecordings(options?)List all recordings with filters
RecordinglistActiveRecordings(roomName?)List currently running recordings
RecordinggetRecording(recordingId)Get recording details
RecordinggetRecordingDownloadUrl(id, expiresIn?)Get temporary download URL
Stream Out (Egress)
EgressstartStream(options)Start stream, recording, or both (mode: record|stream|both)
EgressstopStream(egressId)Stop active stream/recording
EgressgetStreamStatus(egressId)Get stream details and status
EgresslistStreams(options?)List streams with filters (roomName, status, page)
EgressdeleteStream(egressId)Delete a stream record
EgressgetAutoStreamConfig()Get auto-stream configuration
EgressupdateAutoStreamConfig(options)Configure auto-streaming rules
Ingress (Stream In)
IngressstartStreamIn(options)Create RTMP/WHIP ingress endpoint
IngresslistStreamIn(options?)List ingress endpoints
IngressgetStreamIn(id)Get ingress details
IngressstopStreamIn(id)Delete an ingress endpoint

Webhook Events Reference

All webhook events sent by BaxCloud

EventCategoryDescription
Rooms
room.startedRoomsRoom created and active
room.finishedRoomsRoom closed (empty timeout or deleted)
Participants
participant.joinedParticipantsParticipant joined a room
participant.leftParticipantsParticipant left a room
Recording
recording.startedRecordCloud recording started for a room
recording.completedRecordRecording finished, file available for download
recording.failedRecordRecording failed (error details in payload)
Stream Out (Egress)
stream.startedStream OutRTMP stream to YouTube/Twitch/etc. started
stream.updatedStream OutStream status changed (destination connected, etc.)
stream.completedStream OutStream to external platform completed
stream.failedStream OutStream to external platform failed
Stream In (Ingress)
live.startedStream InIngress stream from OBS/encoder started
live.updatedStream InIngress state changed (BUFFERING → ACTIVE)
live.endedStream InIngress stream ended (encoder disconnected)
live.failedStream InIngress stream failed
Tracks
track.publishedTracksParticipant published audio/video track
track.unpublishedTracksParticipant unpublished a track