VDO.Ninja Developer API Sandbox

Your API Key: Loading...

Connecting...

Your Ninja Link: Loading...

You can append VDO.Ninja parameters to this link, treating it like a normal VDO.Ninja link.

Companion Module IFrame API Docs
WebSocket API
HTTP API
Server-Sent Events
HTTP POST
Camera Controls
MIDI Integration
Guest Controls
API Reference
WebSocket API Request Builder
Common Controls (WebSocket)
Layout Controls (WebSocket)

WebSocket API Code Example

JavaScript
// Connect to WebSocket API
const socket = new WebSocket("wss://api.vdo.ninja:443");

// Track connection state
socket.onopen = function() {
  console.log("Connected to VDO.Ninja API");
  // Join with your API ID
  socket.send(JSON.stringify({ "join": "YOUR_API_ID" }));
};

// Handle messages
socket.onmessage = function(event) {
  if (event.data) {
    const data = JSON.parse(event.data);
    console.log("Received:", data);
  }
};

// Reconnection logic (crucial for production)
socket.onclose = function() {
  console.log("Connection closed, attempting to reconnect...");
  setTimeout(() => {
    // Implement reconnection logic here
  }, 1000);
};

// Example commands
function sendCommand(action, value = null, value2 = null, target = null) {
  const msg = { action };
  if (value !== null) msg.value = value;
  if (value2 !== null) msg.value2 = value2;
  if (target !== null) msg.target = target;
  
  if (socket.readyState === WebSocket.OPEN) {
    socket.send(JSON.stringify(msg));
  } else {
    console.error("Socket not connected");
  }
}

// Command examples:
// sendCommand("mic", "toggle");
// sendCommand("camera", false);
// sendCommand("soloVideo", "toggle");
// sendCommand("layout", 2);

// Camera control examples:
// sendCommand("zoom", 0.1);              // Relative zoom in 10%
// sendCommand("zoom", 0.75, "abs");      // Absolute zoom to 75%
// sendCommand("pan", -0.1);              // Relative pan left 10%
// sendCommand("focus", 0.1);             // Relative focus far 10%
// sendCommand("focus", 0.5, "abs");      // Absolute focus to 50%

// For directors - target a guest:
// sendCommand("mic", "toggle", null, "1");          // Toggle guest 1's mic
// sendCommand("ptzZoom", 0.1, null, "2");           // Zoom guest 2's camera in
HTTP GET API Request Builder
https://api.vdo.ninja/YOUR_API_ID/action/target/value
Common Controls (HTTP)
Group Controls (HTTP)

HTTP API Code Example

JavaScript
// HTTP GET API Example
function sendHTTPRequest(apiID, action, target = "null", value = "null") {
  // Construct URL
  const url = `https://api.vdo.ninja/${apiID}/${action}/${target}/${value}`;
  
  // Send request
  fetch(url)
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`);
      }
      return response.text();
    })
    .then(data => {
      // Handle response (could be text or JSON)
      try {
        const jsonData = JSON.parse(data);
        console.log("Response JSON:", jsonData);
      } catch (e) {
        console.log("Response text:", data);
      }
    })
    .catch(error => {
      console.error("Error:", error);
    });
}

// Usage examples:
// sendHTTPRequest("YOUR_API_ID", "mic", "null", "toggle");
// sendHTTPRequest("YOUR_API_ID", "camera", "null", "false");
// sendHTTPRequest("YOUR_API_ID", "joinGroup", "null", "1");

// Camera control examples (relative adjustments only via HTTP):
// sendHTTPRequest("YOUR_API_ID", "zoom", "null", "0.1");    // Zoom in 10%
// sendHTTPRequest("YOUR_API_ID", "zoom", "null", "-0.1");   // Zoom out 10%
// sendHTTPRequest("YOUR_API_ID", "pan", "null", "-0.1");    // Pan left 10%
// sendHTTPRequest("YOUR_API_ID", "focus", "null", "0.1");   // Focus far 10%

// For directors targeting a specific guest
// sendHTTPRequest("YOUR_API_ID", "mic", "1", "toggle");     // Target guest in slot 1
// sendHTTPRequest("YOUR_API_ID", "ptzZoom", "2", "0.1");    // Zoom guest 2's camera in
Server-Sent Events (SSE) Listener

SSE provides a one-way communication channel to receive events from VDO.Ninja without sending requests.

Disconnected

SSE API Code Example

JavaScript
// Server-Sent Events (SSE) Example
function connectToSSE(apiID) {
  // Create EventSource connection
  const eventSource = new EventSource(`https://api.vdo.ninja/sse/${apiID}`);
  
  // Connection opened
  eventSource.onopen = function() {
    console.log("SSE connection established");
  };
  
  // Listen for messages
  eventSource.onmessage = function(event) {
    try {
      const data = JSON.parse(event.data);
      console.log("SSE event:", data);
      
      // Handle different types of events
      if (data.type === "state_update") {
        // Handle state updates
        updateUI(data.state);
      } else if (data.type === "guest_joined") {
        // Handle guest joining
        console.log(`Guest joined: ${data.guestID}`);
      }
      // Add more event handlers as needed
      
    } catch (e) {
      console.error("Error parsing SSE event:", e);
    }
  };
  
  // Handle errors
  eventSource.onerror = function(error) {
    console.error("SSE connection error:", error);
    
    // Close connection
    eventSource.close();
    
    // Implement reconnection logic
    setTimeout(() => {
      console.log("Attempting to reconnect SSE...");
      connectToSSE(apiID);
    }, 3000);
  };
  
  // Return EventSource instance (for later disconnection if needed)
  return eventSource;
}

// Usage:
// const sseConnection = connectToSSE("YOUR_API_ID");
// 
// // To disconnect later:
// // sseConnection.close();
HTTP POST API Request Builder

The HTTP POST method supports all features including the value2 parameter for absolute camera positioning.

HTTP POST API Code Example

JavaScript
// HTTP POST API Example
function sendPOSTRequest(apiID, data) {
  // Construct URL
  const url = `https://api.vdo.ninja/${apiID}`;
  
  // Configure request
  const options = {
    method: 'POST',
    headers: {
      'Content-Type': 'application/json'
    },
    body: JSON.stringify(data)
  };
  
  // Send request
  fetch(url, options)
    .then(response => {
      if (!response.ok) {
        throw new Error(`HTTP error! Status: ${response.status}`);
      }
      return response.json();
    })
    .then(data => {
      console.log("Response:", data);
    })
    .catch(error => {
      console.error("Error:", error);
    });
}

// Usage examples:
// sendPOSTRequest("YOUR_API_ID", {
//   action: "mic",
//   value: "toggle"
// });
//
// Camera control with absolute positioning:
// sendPOSTRequest("YOUR_API_ID", {
//   action: "zoom",
//   value: 0.75,
//   value2: "abs"  // Sets zoom to exactly 75%
// });
//
// Camera control with relative adjustments:
// sendPOSTRequest("YOUR_API_ID", {
//   action: "pan",
//   value: -0.1    // Pan left by 10%
// });
//
// sendPOSTRequest("YOUR_API_ID", {
//   action: "layout",
//   value: [
//     {"x":0,"y":0,"w":50,"h":100,"slot":0},
//     {"x":50,"y":0,"w":50,"h":100,"slot":1}
//   ]
// });
//
// For directors targeting a specific guest:
// sendPOSTRequest("YOUR_API_ID", {
//   action: "ptzZoom",
//   target: "2", 
//   value: 0.1     // Zoom in guest 2's camera by 10%
// });
Camera Controls (PTZ)

Remote control compatible camera hardware using pan, tilt, zoom, focus, and exposure commands. Supports both relative and absolute positioning.

Zoom

Absolute Zoom (0-2x):
1.0x

Focus

Absolute Focus (0-1):
0.5

Pan & Tilt

Absolute Pan (-1 to +1):
0
Absolute Tilt (-1 to +1):
0

Exposure

Absolute Exposure (0-1):
0.5

Camera Presets

PTZ Controls Code Example

JavaScript
// Camera Control (PTZ) Example
function sendCameraCommand(apiID, action, value, value2 = null, target = null) {
  // Using WebSocket (preferred for responsive camera control)
  if (socket && socket.readyState === WebSocket.OPEN) {
    const command = { action, value };
    if (value2 !== null) command.value2 = value2;
    if (target !== null) command.target = target;
    
    socket.send(JSON.stringify(command));
  } 
  // Using HTTP POST (supports all features including value2)
  else {
    const url = `https://api.vdo.ninja/${apiID}`;
    const data = { action, value };
    if (value2 !== null) data.value2 = value2;
    if (target !== null) data.target = target;
    
    fetch(url, {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify(data)
    })
    .then(response => response.json())
    .then(data => console.log("Response:", data))
    .catch(error => console.error("Error:", error));
  }
}

// RELATIVE ADJUSTMENTS (change from current position)
// sendCameraCommand("YOUR_API_ID", "zoom", 0.1);        // Zoom in by 10%
// sendCameraCommand("YOUR_API_ID", "zoom", -0.1);       // Zoom out by 10%
// sendCameraCommand("YOUR_API_ID", "focus", 0.1);       // Focus farther by 10%
// sendCameraCommand("YOUR_API_ID", "focus", -0.1);      // Focus nearer by 10%
// sendCameraCommand("YOUR_API_ID", "pan", -0.1);        // Pan left by 10%
// sendCameraCommand("YOUR_API_ID", "pan", 0.1);         // Pan right by 10%
// sendCameraCommand("YOUR_API_ID", "tilt", 0.1);        // Tilt up by 10%
// sendCameraCommand("YOUR_API_ID", "tilt", -0.1);       // Tilt down by 10%
// sendCameraCommand("YOUR_API_ID", "exposure", 0.1);    // Increase exposure by 10%
// sendCameraCommand("YOUR_API_ID", "exposure", -0.1);   // Decrease exposure by 10%

// ABSOLUTE POSITIONING (set to exact values)
// sendCameraCommand("YOUR_API_ID", "zoom", 1.5, "abs");      // Set zoom to 1.5x
// sendCameraCommand("YOUR_API_ID", "focus", 0.75, "abs");    // Set focus to 75%
// sendCameraCommand("YOUR_API_ID", "pan", 0, "abs");         // Center pan
// sendCameraCommand("YOUR_API_ID", "pan", -0.5, "abs");      // Pan 50% left
// sendCameraCommand("YOUR_API_ID", "tilt", 0.25, "abs");     // Tilt 25% up
// sendCameraCommand("YOUR_API_ID", "exposure", 0.8, "abs");  // Set exposure to 80%

// Camera presets using absolute positioning
function setCameraPreset(preset) {
  switch(preset) {
    case 1: // Center position
      sendCameraCommand("YOUR_API_ID", "zoom", 1.0, "abs");
      sendCameraCommand("YOUR_API_ID", "pan", 0, "abs");
      sendCameraCommand("YOUR_API_ID", "tilt", 0, "abs");
      break;
    case 2: // Wide shot
      sendCameraCommand("YOUR_API_ID", "zoom", 0.5, "abs");
      sendCameraCommand("YOUR_API_ID", "pan", 0, "abs");
      sendCameraCommand("YOUR_API_ID", "tilt", 0, "abs");
      break;
    case 3: // Close-up
      sendCameraCommand("YOUR_API_ID", "zoom", 2.0, "abs");
      sendCameraCommand("YOUR_API_ID", "pan", 0, "abs");
      sendCameraCommand("YOUR_API_ID", "tilt", 0, "abs");
      break;
  }
}

// Targeting a specific guest's camera (for directors)
// sendCameraCommand("YOUR_API_ID", "ptzZoom", 0.1, null, "2");    // Zoom guest 2's camera in
// sendCameraCommand("YOUR_API_ID", "ptzPan", -0.5, "abs", "1");   // Set guest 1's pan to 50% left
// Note: guest-targeted exposure is not currently part of the director targetGuest API.
MIDI Integration

Control VDO.Ninja using MIDI controllers with various mapping options.

MIDI access not initialized
No MIDI message received

Default MIDI Mappings

VDO.Ninja supports several MIDI mapping schemes, which can be configured using the &midiHotkeys parameter.

Standard Mapping (&midiHotkeys=1)
  • G3: Toggle chat
  • A3: Toggle mic
  • B3: Toggle video
  • C4: Toggle screenshare
  • D4: Hangup
  • E4: Raise hand
  • F4: Toggle recording
  • G4: Director audio
  • A4: Director hangup
  • B4: Toggle speaker
Alternate Mapping (&midiHotkeys=2)
  • G1: Toggle chat
  • A1: Toggle mic
  • B1: Toggle video
  • C2: Toggle screenshare
  • D2: Hangup
  • E2: Raise hand
  • F2: Toggle recording
  • G2: Director audio
  • A2: Director hangup
  • B2: Toggle speaker
CC-Based Controls (&midiHotkeys=3)

Uses note C1 with different velocity values:

  • C1 + velocity 0: Toggle chat
  • C1 + velocity 1: Toggle mic
  • C1 + velocity 2: Toggle video
  • C1 + velocity 3: Toggle screenshare
  • C1 + velocity 4: Hangup
  • C1 + velocity 5: Raise hand
  • C1 + velocity 6: Toggle recording
  • C1 + velocity 7: Director audio
  • C1 + velocity 8: Director hangup
  • C1 + velocity 9: Toggle speaker
Advanced MIDI Controls

CC 110 Commands:

  • Value 20: Zoom in (+10%)
  • Value 21: Zoom out (-10%)
  • Value 22: Pan left (-10%)
  • Value 23: Pan right (+10%)
  • Value 24: Tilt up (+10%)
  • Value 25: Tilt down (-10%)
  • Value 26: Exposure up (+10%)
  • Value 27: Exposure down (-10%)
  • Value 28: Focus near (-10%)
  • Value 29: Focus far (+10%)
  • Value 30-32: Camera presets 1-3

CC 80-84 (Absolute Control):

  • CC80: Zoom (0-127 → 0-2x)
  • CC81: Pan (0-127 → -1 to +1)
  • CC82: Tilt (0-127 → -1 to +1)
  • CC83: Exposure (0-127 → 0-1)
  • CC84: Focus (0-127 → 0-1)

MIDI API Code Example

JavaScript
// MIDI Integration Example
function initializeMIDI() {
  // Check if Web MIDI API is supported
  if (!navigator.requestMIDIAccess) {
    console.error("Web MIDI API not supported in this browser");
    return Promise.reject("MIDI not supported");
  }
  
  // Request MIDI access
  return navigator.requestMIDIAccess({ sysex: false })
    .then(midiAccess => {
      console.log("MIDI Access granted");
      
      // Get MIDI inputs
      const inputs = midiAccess.inputs.values();
      const devices = [];
      
      // Setup devices
      for (let input = inputs.next(); input && !input.done; input = inputs.next()) {
        devices.push(input.value);
        setupMIDIDevice(input.value);
      }
      
      // Listen for device connection/disconnection
      midiAccess.onstatechange = function(e) {
        console.log("MIDI state change:", e.port.name, e.port.state);
      };
      
      return { midiAccess, devices };
    })
    .catch(error => {
      console.error("Failed to get MIDI access:", error);
      throw error;
    });
}

function setupMIDIDevice(inputDevice) {
  // Set up MIDI message handler
  inputDevice.onmidimessage = function(message) {
    // Extract MIDI data
    const command = message.data[0];
    const note = message.data[1];
    const velocity = message.data[2];
    
    console.log(`MIDI message - Command: ${command}, Note: ${note}, Velocity: ${velocity}`);
    
    // Handle Note On messages (144 = Note On, channel 1)
    if (command === 144 && velocity > 0) {
      handleNoteOn(note, velocity);
    }
    // Handle Note Off messages (128 = Note Off, channel 1)
    else if (command === 128 || (command === 144 && velocity === 0)) {
      handleNoteOff(note);
    }
    // Handle Control Change messages (176 = CC, channel 1)
    else if (command === 176) {
      handleControlChange(note, velocity);
    }
  };
}

function handleControlChange(cc, value) {
  // Map control change messages to actions
  
  // CC110 - Advanced commands
  if (cc === 110) {
    switch(value) {
      case 20: sendCommand("zoom", 0.1); break;           // Zoom in
      case 21: sendCommand("zoom", -0.1); break;          // Zoom out
      case 22: sendCommand("pan", -0.1); break;           // Pan left
      case 23: sendCommand("pan", 0.1); break;            // Pan right
      case 24: sendCommand("tilt", 0.1); break;           // Tilt up
      case 25: sendCommand("tilt", -0.1); break;          // Tilt down
      case 26: sendCommand("exposure", 0.1); break;       // Exposure up
      case 27: sendCommand("exposure", -0.1); break;      // Exposure down
      case 28: sendCommand("focus", -0.1); break;         // Focus near
      case 29: sendCommand("focus", 0.1); break;          // Focus far
      case 30: // Camera preset 1
        sendCommand("zoom", 1.0, "abs");
        sendCommand("pan", 0, "abs");
        sendCommand("tilt", 0, "abs");
        break;
      // Add more CC110 values as needed
    }
  }
  // CC80-84: Absolute camera controls
  else if (cc >= 80 && cc <= 84) {
    const normalizedValue = value / 127; // 0-1 range
    
    switch(cc) {
      case 80: // Zoom absolute (0-127 maps to 0-2x zoom)
        sendCommand("zoom", normalizedValue * 2, "abs");
        break;
      case 81: // Pan absolute (0-127 maps to -1 to +1)
        sendCommand("pan", (normalizedValue * 2) - 1, "abs");
        break;
      case 82: // Tilt absolute (0-127 maps to -1 to +1)
        sendCommand("tilt", (normalizedValue * 2) - 1, "abs");
        break;
      case 83: // Exposure absolute (0-127 maps to 0-1)
        sendCommand("exposure", normalizedValue, "abs");
        break;
      case 84: // Focus absolute (0-127 maps to 0-1)
        sendCommand("focus", normalizedValue, "abs");
        break;
    }
  }
}

// Helper function to convert MIDI note number to note name
function getNoteNameFromNumber(noteNumber) {
  const notes = ["C", "C#", "D", "D#", "E", "F", "F#", "G", "G#", "A", "A#", "B"];
  const octave = Math.floor(noteNumber / 12) - 1;
  const noteName = notes[noteNumber % 12];
  return noteName + octave;
}

// Usage:
// initializeMIDI()
//   .then(midi => console.log("MIDI ready with devices:", midi.devices))
//   .catch(error => console.error("MIDI setup failed:", error));
Guest Controls (Director Mode)

These controls allow directors to manage remote guests via the API.

Guest Mic Volume:
100

Guest Control Code Example

JavaScript
// Guest Control Example (Director Mode)
function controlGuest(apiID, target, action, value = null, value2 = null, method = "websocket") {
  if (method === "websocket") {
    // WebSocket method (supports all features including value2)
    if (socket && socket.readyState === WebSocket.OPEN) {
      const msg = {
        target: target,
        action: action
      };
      
      if (value !== null) msg.value = value;
      if (value2 !== null) msg.value2 = value2;
      
      socket.send(JSON.stringify(msg));
      console.log("Sent guest command via WebSocket:", msg);
    } else {
      console.error("WebSocket not connected");
    }
  } else if (method === "http") {
    // HTTP method (limited - no value2 support)
    const targetStr = target || "null";
    const valueStr = value !== null ? value : "null";
    const url = `https://api.vdo.ninja/${apiID}/${action}/${targetStr}/${valueStr}`;
    
    fetch(url)
      .then(response => response.text())
      .then(data => console.log("Guest command response:", data))
      .catch(error => console.error("Error sending guest command:", error));
  }
}

// Basic guest control examples:
// controlGuest("YOUR_API_ID", "1", "mic", "toggle");      // Toggle mic for guest 1
// controlGuest("YOUR_API_ID", "2", "camera", false);      // Turn off camera for guest 2
// controlGuest("YOUR_API_ID", "3", "addScene", 1);        // Add guest 3 to scene 1
// controlGuest("YOUR_API_ID", "1", "sendDirectorChat", "You're live in 10 seconds");
// controlGuest("YOUR_API_ID", "2", "volume", 85);         // Set guest 2 volume to 85%
// controlGuest("YOUR_API_ID", "1", "rotate", true);       // Rotate guest 1 video by +90 degrees
// controlGuest("YOUR_API_ID", "1", "rotate", 180);        // Set guest 1 rotation explicitly
// controlGuest("YOUR_API_ID", "4", "forward", "room123"); // Transfer guest 4 to room123

// Camera/PTZ control for specific guests:
// Relative adjustments
// controlGuest("YOUR_API_ID", "1", "ptzZoom", 0.1);           // Zoom guest 1's camera in by 10%
// controlGuest("YOUR_API_ID", "2", "ptzPan", -0.1);           // Pan guest 2's camera left by 10%
// controlGuest("YOUR_API_ID", "3", "ptzFocus", 0.1);          // Focus guest 3's camera farther
// controlGuest("YOUR_API_ID", "4", "ptzAutofocus", "manual"); // Disable guest 4 autofocus

// Absolute positioning (WebSocket or HTTP POST)
// controlGuest("YOUR_API_ID", "1", "ptzZoom", 1.5, "abs");    // Set guest 1's zoom to 1.5x
// controlGuest("YOUR_API_ID", "2", "ptzPan", 0, "abs");       // Center guest 2's pan
// controlGuest("YOUR_API_ID", "3", "ptzTilt", -0.25, "abs");  // Tilt guest 3's camera 25% down
// controlGuest("YOUR_API_ID", "4", "requestResolution", "1280x720"); // Request 720p preview
VDO.Ninja API Reference

Complete reference for all supported API commands, parameters, and response formats.

API Overview

The VDO.Ninja API supports multiple communication methods:

  • WebSocket API: Real-time bidirectional communication (preferred for most uses)
  • HTTP GET API: Simple REST-style requests, compatible with hotkey systems
  • HTTP POST API: For complex data structures like layout objects and supports value2 parameter
  • Server-Sent Events (SSE): One-way communication channel for receiving updates
  • MIDI Integration: Control via MIDI devices using various mapping schemes

For integrations with BitFocus Companion, check out the official Companion module.

For custom embeds, refer to the IFrame API Documentation.

Command Reference

The following tables list all available commands, their parameters, and what they do.

Self Controls

Action Target Value Details
speaker null true/false/toggle Control local speaker (audio playback)
mic null true/false/toggle Control local microphone
camera null true/false/toggle Control local camera (same as video)
video null true/false/toggle Control local camera (alternate command)
volume null true/false/0-200 Control playback volume of all audio tracks (true=100%, false=0%, 200=max boost)
record null true/false Start/stop recording the local video stream
bitrate null true/false/integer Control video bitrate (true=reset, false=pause, integer=kbps)
panning null true/false/0-180 Control stereo panning (90=center)
reload null null Reload the current page
hangup null null Disconnect current session
togglehand null null Toggle raised hand status
raisehand null null Alias of togglehand
togglescreenshare null null Toggle screen sharing
forceKeyframe null null Force keyframe ("rainbow puke fix")
sendChat null string Send chat message to all connected users
showChatOverlay null string Display an overlay-style chat message locally
getDetails null null Get detailed state information
requestStats null null Get detailed live stats for the page, including peer stats
getStats null or stream ID null Get quick inbound/outbound stats summary
getGuestList null null Get the current list of connected guests and identifiers
soloVideo null true/false/toggle Highlight video for all guests (director only)
setBufferDelay null or stream ID milliseconds Set playback delay for incoming media
activeSpeaker null toggle/false/1/2/3 Enable or configure active-speaker mode
tallylight null onair/active/standby/off/integer Override tally-light state
aspectRatio null decimal or ratio string Set the local camera aspect-ratio constraint
videoConstraint constraint name constraint value in value2 Set a local camera constraint; use WebSocket or HTTP POST when passing value2

Layout Controls

Action Value Details
layout integer/object/array Switch to layout by index (0=auto-mix, 1-8=custom layouts) or set custom layout with object

Group Controls

Action Value Details
group 1-8 Toggle in/out of specified group
joinGroup 1-8 Join specified group
leaveGroup 1-8 Leave specified group
viewGroup 1-8 Toggle preview of specified group
joinViewGroup 1-8 Preview specified group
leaveViewGroup 1-8 Stop previewing specified group

Camera Control (PTZ)

Action Value Value2 Details
zoom decimal (-1 to 1 relative, 0-2 absolute) "abs" or "true" (optional) Adjust zoom. Relative: positive=in, negative=out. Absolute: 0-2x zoom when value2="abs"
focus decimal (-1 to 1 relative, 0-1 absolute) "abs" or "true" (optional) Adjust focus. Relative: positive=far, negative=near. Absolute: 0-1 range when value2="abs"
pan decimal (-1 to 1) n/a Adjust pan (always absolute). -1=full left, 0=center, 1=full right
tilt decimal (-1 to 1 relative or absolute) "abs" or "true" (optional) Adjust tilt. Relative: positive=up, negative=down. Absolute: -1 to 1 range when value2="abs"
exposure decimal (-1 to 1 relative, 0-1 absolute) "abs" or "true" (optional) Adjust exposure. Relative: positive=brighter, negative=darker. Absolute: 0-1 range when value2="abs"

Self-targeted camera controls use zoom, focus, pan, tilt, and exposure. When targeting a guest as a director, use the guest-specific ptz* or remote* actions instead.

Guest Controls (Director Mode)

Action Target Value Value2 Details
forward guest slot/ID room name n/a Transfer guest to specified room
addScene guest slot/ID 0-8 or scene name n/a Toggle guest in/out of specified scene
muteScene guest slot/ID scene (optional) n/a Toggle guest's mic in scenes
mic guest slot/ID true/false/toggle n/a Control guest's microphone
camera guest slot/ID true/false/toggle n/a Control guest's camera
video guest slot/ID true/false/toggle n/a Control guest's camera (alternate command)
hangup guest slot/ID null n/a Disconnect guest
soloChat guest slot/ID null n/a Toggle one-way solo chat with guest
soloChatBidirectional guest slot/ID null n/a Toggle two-way solo chat with guest
speaker guest slot/ID null n/a Toggle guest's speaker
display guest slot/ID null n/a Toggle guest's display (ability to see video)
rotate guest slot/ID true/false/90/180/270 n/a Rotate guest video. true advances +90 degrees; false resets rotation.
group guest slot/ID 1-8 n/a Toggle guest in/out of specified group
forceKeyframe guest slot/ID null n/a Trigger keyframe for guest (fix rainbow artifacts)
soloVideo guest slot/ID null n/a Toggle highlighting guest's video
sendChat guest slot/ID message text n/a Send private chat message to guest
sendDirectorChat guest slot/ID message text n/a Send message and overlay it on guest's screen
sendPinnedDirectorChat guest slot/ID message text n/a Send a pinned overlay chat message to the guest
volume guest slot/ID 0-200 n/a Set guest's microphone volume
startRoomTimer guest slot/ID seconds n/a Start countdown timer for guest
pauseRoomTimer guest slot/ID null n/a Pause timer for guest
stopRoomTimer guest slot/ID null n/a Stop timer for guest
mixorder guest slot/ID -1 or 1 n/a Adjust guest's position in the mixer (-1=up, 1=down)
channel guest slot/ID 0, 1 or 2 n/a Sets the PGM/Mic channel to 1 or 2 (0 resets)
mirror / mirrorGuest / remoteMirror guest slot/ID true/false/toggle n/a Toggle or set director-enforced mirroring on the guest sender
ptzZoom / remoteZoom guest slot/ID decimal (see Camera Control) "abs" or "true" (optional) Control guest zoom
ptzFocus / remoteFocus guest slot/ID decimal (see Camera Control) "abs" or "true" (optional) Control guest focus
ptzPan / remotePan guest slot/ID decimal (see Camera Control) "abs" or "true" (optional) Control guest pan
ptzTilt / remoteTilt guest slot/ID decimal (see Camera Control) "abs" or "true" (optional) Control guest tilt
ptzAutofocus / remoteAutofocus / resetAutofocus guest slot/ID true/false/manual/off n/a Enable or disable guest autofocus
requestResolution guest slot/ID WIDTHxHEIGHT n/a Request a specific preview resolution from the guest
requestAspectRatio guest slot/ID decimal or ratio string max dimension (optional) Request a preview resolution matching an aspect ratio
setWidth guest slot/ID integer n/a Request guest capture width
setHeight guest slot/ID integer n/a Request guest capture height
setAspectRatio guest slot/ID decimal n/a Request guest capture aspect ratio
refreshVideo / refreshCamera guest slot/ID null n/a Ask the guest to refresh camera/video tracks
refreshConnection / restartConnection guest slot/ID null n/a Ask the guest to restart the connection
recoverStream / refreshAll guest slot/ID null n/a Ask the guest to recover both media and connection state

rotate and the guest-targeted ptz* / remote* commands are director-side controls. They are not standalone untargeted local commands for a guest page using ?push=...&api=....

Response Formats

Responses from the API depend on the method used:

  • HTTP GET: Responses include simple text values like true, false, null, fail, or a specific value. For object responses like getDetails, you'll receive JSON.
  • WebSocket: Responses are JSON objects containing the result along with the original request parameters and any custom data fields you included.
  • HTTP POST: Responses are JSON objects with similar structure to WebSocket responses.
  • SSE: Events are JSON objects containing state updates and other notifications.

Camera Control Details

The camera control commands support both relative and absolute positioning:

  • Relative adjustments: Changes are applied from the current position. Use decimal values like 0.1 for +10% or -0.1 for -10%.
  • Absolute positioning: Set exact values by adding value2: "abs" (WebSocket/POST) or using compatible ranges.
Camera Control Examples
// Camera Control Value Ranges:
// zoom: Relative -1 to 1, Absolute 0 to 2 (0=minimum zoom, 2=2x zoom)
// focus: Relative -1 to 1, Absolute 0 to 1 (0=near, 1=far)
// pan: Always absolute -1 to 1 (-1=left, 0=center, 1=right)
// tilt: Relative -1 to 1, Absolute -1 to 1 (-1=down, 0=center, 1=up)
// exposure: Relative -1 to 1, Absolute 0 to 1 (0=dark, 1=bright)

// WebSocket Examples:
// Relative: {"action": "zoom", "value": 0.1}                    // Zoom in 10%
// Absolute: {"action": "zoom", "value": 1.5, "value2": "abs"}   // Set zoom to 1.5x

// HTTP POST Examples:
// Relative: POST body: {"action": "focus", "value": -0.1}
// Absolute: POST body: {"action": "exposure", "value": 0.8, "value2": "abs"}

// Note: HTTP GET only supports relative adjustments

Custom Layout Format

When using the layout command, you can provide a custom layout object or array:

Layout Object Example
// Single layout example
{
  "action": "layout",
  "value": [
    {"x": 0, "y": 0, "w": 50, "h": 100, "slot": 0},
    {"x": 50, "y": 0, "w": 50, "h": 100, "slot": 1}
  ]
}

// Using URL parameter to define multiple layouts
// ?layouts=[[{"x":0,"y":0,"w":100,"h":100,"slot":0}],[{"x":0,"y":0,"w":50,"h":100,"slot":0},{"x":50,"y":0,"w":50,"h":100,"slot":1}]]

// Layout properties:
// x, y: Position (percentage of container)
// w, h: Width and height (percentage of container)
// slot: Guest slot number (0-indexed)
// c: Crop to fit (true/false)
// z: Z-index (layer)

// To switch layouts:
// {"action": "layout", "value": 0} // Auto-mix
// {"action": "layout", "value": 1} // First custom layout
// {"action": "layout", "value": 2} // Second custom layout
API Request/Response Logger