Stagemonitor

API Documentation

Use the Stagemonitor API to control your monitors programmatically.

Table of Contents

Authentication

Stagemonitor uses two types of identifiers:

IdentifierPurposeWhere to find
Project ID Identifies your project in all API calls Control panel → Settings
API Key Authenticates protected operations Control panel → Settings

Public Endpoints

Some endpoints only require the id parameter (Project ID). These are suitable for basic control operations.

Protected Endpoints AUTH

Endpoints marked with AUTH require authentication via API Key. You can provide the API key in two ways:

Option 1: HTTP Header (Recommended)
X-API-Key: your_api_key_here
Option 2: Query Parameter
&api_key=your_api_key_here
Security Note: Keep both your Project ID and API Key secret. Anyone with access to them can control your Stagemonitor. The HTTP header method is recommended as it keeps the API key out of server logs and browser history.

Base URL

https://stagemonitor.app/api/

Countdown API

Control the countdown timer on your monitor.

GET Set Countdown

Set a new countdown timer with specific hours, minutes, and seconds.

URL
/api/countdown/?id={PROJECT_ID}&hh={HOURS}&mm={MINUTES}&ss={SECONDS}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
hhintegerYesHours (0-99)
mmintegerYesMinutes (0-59)
ssintegerYesSeconds (0-59)
redirbooleanNoSet to "true" to redirect back to referrer after request
Response
{ "success": true, "message": "Countdown updated" }
Examples

cURL:

# Set a 10 minute countdown curl "https://stagemonitor.app/api/countdown/?id=abc123def456&hh=0&mm=10&ss=0" # Set a 1 hour 30 minute countdown curl "https://stagemonitor.app/api/countdown/?id=abc123def456&hh=1&mm=30&ss=0" # Set countdown to zero (stop) curl "https://stagemonitor.app/api/countdown/?id=abc123def456&hh=0&mm=0&ss=0"

JavaScript:

// Set a 10 minute countdown fetch('https://stagemonitor.app/api/countdown/?id=abc123def456&hh=0&mm=10&ss=0') .then(response => response.json()) .then(data => console.log(data)); // Using async/await async function setCountdown(projectId, hours, minutes, seconds) { const url = `https://stagemonitor.app/api/countdown/?id=${projectId}&hh=${hours}&mm=${minutes}&ss=${seconds}`; const response = await fetch(url); return await response.json(); } // Usage await setCountdown('abc123def456', 0, 10, 0);

Python:

import requests PROJECT_ID = "abc123def456" # Set a 10 minute countdown response = requests.get( "https://stagemonitor.app/api/countdown/", params={"id": PROJECT_ID, "hh": 0, "mm": 10, "ss": 0} ) print(response.json()) # Helper function def set_countdown(project_id, hours, minutes, seconds): return requests.get( "https://stagemonitor.app/api/countdown/", params={"id": project_id, "hh": hours, "mm": minutes, "ss": seconds} ).json()

GET Get Countdown Display

Get the current countdown value formatted for display. Returns negative time when countdown has passed zero.

URL
/api/countdown/get.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Response

Returns plain text with the countdown in HH:MM:SS format. Negative values are prefixed with -.

Examples

cURL:

# Get current countdown value curl "https://stagemonitor.app/api/countdown/get.php?id=abc123def456" # Response examples: # 00:09:45 (9 minutes 45 seconds remaining) # 00:00:00 (countdown finished) # -00:02:30 (2 minutes 30 seconds overtime)

JavaScript:

// Get countdown as plain text fetch('https://stagemonitor.app/api/countdown/get.php?id=abc123def456') .then(response => response.text()) .then(countdown => console.log('Countdown:', countdown)); // Parse countdown time async function getCountdown(projectId) { const response = await fetch(`https://stagemonitor.app/api/countdown/get.php?id=${projectId}`); return await response.text(); } // Check if overtime async function isOvertime(projectId) { const countdown = await getCountdown(projectId); return countdown.startsWith('-'); }

Python:

import requests PROJECT_ID = "abc123def456" # Get countdown display value response = requests.get( "https://stagemonitor.app/api/countdown/get.php", params={"id": PROJECT_ID} ) countdown = response.text print(f"Current countdown: {countdown}") # Check if overtime is_overtime = countdown.startswith('-') print(f"Overtime: {is_overtime}")

GET Add Time to Countdown AUTH REQUIRED

Add or subtract minutes from the current countdown. Useful for extending or shortening time during an event.

URL
/api/countdown/add.php?id={PROJECT_ID}&min={MINUTES}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
minintegerYesMinutes to add (negative to subtract)
redirbooleanNoSet to "true" to redirect back to referrer
Authentication

Requires API Key via X-API-Key header or api_key query parameter.

Response
{ "success": true, "message": "Added 5 minutes" }
Examples

cURL:

# Add 5 minutes (using header) curl -H "X-API-Key: your_api_key_here" \ "https://stagemonitor.app/api/countdown/add.php?id=abc123def456&min=5" # Subtract 2 minutes (using query parameter) curl "https://stagemonitor.app/api/countdown/add.php?id=abc123def456&min=-2&api_key=your_api_key_here" # Add 10 minutes curl -H "X-API-Key: your_api_key_here" \ "https://stagemonitor.app/api/countdown/add.php?id=abc123def456&min=10"

JavaScript:

const PROJECT_ID = 'abc123def456'; const API_KEY = 'your_api_key_here'; // Add 5 minutes using header (recommended) fetch(`https://stagemonitor.app/api/countdown/add.php?id=${PROJECT_ID}&min=5`, { headers: { 'X-API-Key': API_KEY } }) .then(response => response.json()) .then(data => console.log(data)); // Subtract 2 minutes async function addMinutes(projectId, apiKey, minutes) { const response = await fetch( `https://stagemonitor.app/api/countdown/add.php?id=${projectId}&min=${minutes}`, { headers: { 'X-API-Key': apiKey } } ); return await response.json(); } // Usage await addMinutes(PROJECT_ID, API_KEY, -2); // Subtract 2 minutes

Python:

import requests PROJECT_ID = "abc123def456" API_KEY = "your_api_key_here" # Add 5 minutes using header (recommended) response = requests.get( "https://stagemonitor.app/api/countdown/add.php", params={"id": PROJECT_ID, "min": 5}, headers={"X-API-Key": API_KEY} ) print(response.json()) # Subtract 3 minutes response = requests.get( "https://stagemonitor.app/api/countdown/add.php", params={"id": PROJECT_ID, "min": -3}, headers={"X-API-Key": API_KEY} ) print(response.json()) # Helper function def add_countdown_time(project_id, api_key, minutes): return requests.get( "https://stagemonitor.app/api/countdown/add.php", params={"id": project_id, "min": minutes}, headers={"X-API-Key": api_key} ).json()

GET Pause/Resume Countdown

Toggle the pause state of the countdown. When paused, the countdown freezes at its current value.

URL
/api/countdown/pause.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Response
{ "success": true, "paused": true, "message": "Countdown paused" } // or when resuming: { "success": true, "paused": false, "message": "Countdown resumed" }
Examples

cURL:

# Toggle pause state curl "https://stagemonitor.app/api/countdown/pause.php?id=abc123def456"

JavaScript:

// Toggle pause fetch('https://stagemonitor.app/api/countdown/pause.php?id=abc123def456') .then(response => response.json()) .then(data => { console.log('Paused:', data.paused); }); // With async/await async function togglePause(projectId) { const response = await fetch(`https://stagemonitor.app/api/countdown/pause.php?id=${projectId}`); const data = await response.json(); return data.paused; }

Python:

import requests PROJECT_ID = "abc123def456" # Toggle pause response = requests.get( "https://stagemonitor.app/api/countdown/pause.php", params={"id": PROJECT_ID} ) data = response.json() print(f"Paused: {data['paused']}")

Note/Message API

Display messages on the monitor screen.

GET Set Note/Message

Set a note or message to display on the monitor. HTML tags are sanitized for security.

URL
/api/note/?id={PROJECT_ID}¬e={MESSAGE}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
notestringYesThe message to display (URL encoded). Empty string clears the note.
Response
{ "success": true, "message": "Note updated" }
Examples

cURL:

# Set a simple note curl "https://stagemonitor.app/api/note/?id=abc123def456¬e=Welcome%20to%20the%20event" # Set "LIVE" indicator curl "https://stagemonitor.app/api/note/?id=abc123def456¬e=LIVE" # Set note with special characters (URL encoded) curl "https://stagemonitor.app/api/note/?id=abc123def456¬e=Break%20%2810%20min%29" # Clear the note (empty string) curl "https://stagemonitor.app/api/note/?id=abc123def456¬e="

JavaScript:

const PROJECT_ID = 'abc123def456'; // Set a note (URL encode the message) const message = 'Welcome to the event!'; fetch(`https://stagemonitor.app/api/note/?id=${PROJECT_ID}¬e=${encodeURIComponent(message)}`) .then(response => response.json()) .then(data => console.log(data)); // Helper function async function setNote(projectId, note) { const url = `https://stagemonitor.app/api/note/?id=${projectId}¬e=${encodeURIComponent(note)}`; const response = await fetch(url); return await response.json(); } // Usage examples await setNote(PROJECT_ID, 'LIVE'); // Show "LIVE" await setNote(PROJECT_ID, 'Break (10 min)'); // Show with special chars await setNote(PROJECT_ID, ''); // Clear note

Python:

import requests from urllib.parse import quote PROJECT_ID = "abc123def456" # Set a note response = requests.get( "https://stagemonitor.app/api/note/", params={"id": PROJECT_ID, "note": "Welcome to the event!"} ) print(response.json()) # Clear note response = requests.get( "https://stagemonitor.app/api/note/", params={"id": PROJECT_ID, "note": ""} ) # Helper function def set_note(project_id, note): return requests.get( "https://stagemonitor.app/api/note/", params={"id": project_id, "note": note} ).json()

GET Get Note

Get the current note/message.

URL
/api/note/get.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Response

Returns plain text with the current note. Empty response if no note is set.

Examples

cURL:

# Get current note curl "https://stagemonitor.app/api/note/get.php?id=abc123def456" # Response (plain text): # Welcome to the event!

JavaScript:

// Get note as plain text fetch('https://stagemonitor.app/api/note/get.php?id=abc123def456') .then(response => response.text()) .then(note => { if (note) { console.log('Current note:', note); } else { console.log('No note set'); } });

Python:

import requests PROJECT_ID = "abc123def456" response = requests.get( "https://stagemonitor.app/api/note/get.php", params={"id": PROJECT_ID} ) note = response.text print(f"Current note: {note}" if note else "No note set")

Program/Schedule API

Manage program entries and schedules for your event.

GET Get Program

Get the full program/schedule including all entries and the currently active entry.

URL
/api/program/get.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Response
{ "ok": true, "program": [ { "id": "entry_1", "name": "Opening Remarks", "message": "Welcome everyone!", "countdown": "00:15:00", "scheduled": "09:00", "completed": false }, { "id": "entry_2", "name": "Keynote Speech", "message": "", "countdown": "00:45:00", "scheduled": "09:15", "completed": false } ], "activeEntryId": "entry_1" }
Examples

cURL:

# Get full program curl "https://stagemonitor.app/api/program/get.php?id=abc123def456"

JavaScript:

// Get program data fetch('https://stagemonitor.app/api/program/get.php?id=abc123def456') .then(response => response.json()) .then(data => { console.log('Active entry:', data.activeEntryId); console.log('Program entries:', data.program); // Find active entry const activeEntry = data.program.find(e => e.id === data.activeEntryId); if (activeEntry) { console.log('Currently running:', activeEntry.name); } }); // Get next upcoming entry async function getNextEntry(projectId) { const response = await fetch(`https://stagemonitor.app/api/program/get.php?id=${projectId}`); const data = await response.json(); const activeIndex = data.program.findIndex(e => e.id === data.activeEntryId); return data.program[activeIndex + 1] || null; }

Python:

import requests PROJECT_ID = "abc123def456" response = requests.get( "https://stagemonitor.app/api/program/get.php", params={"id": PROJECT_ID} ) data = response.json() print(f"Active entry: {data['activeEntryId']}") print(f"Total entries: {len(data['program'])}") # List all entries for entry in data['program']: status = "ACTIVE" if entry['id'] == data['activeEntryId'] else "" print(f" - {entry['name']} ({entry['countdown']}) {status}")

POST Update Program Entry AUTH REQUIRED

Update a specific program entry's details.

URL
/api/program/update.php?id={PROJECT_ID}&entry_id={ENTRY_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID (query parameter)
entry_idstringYesThe entry ID to update (query parameter)
Request Body (form data)
FieldTypeRequiredDescription
namestringNoEntry name/title
messagestringNoNote/message for this entry
countdownstringNoCountdown duration (HH:MM:SS format)
scheduledstringNoScheduled time (HH:MM format)
Authentication

Requires API Key via X-API-Key header or api_key query parameter.

Response
{ "ok": true, "message": "Entry updated" }
Examples

cURL:

# Update entry name and countdown curl -X POST \ -H "X-API-Key: your_api_key_here" \ -d "name=Extended%20Keynote&countdown=01:00:00" \ "https://stagemonitor.app/api/program/update.php?id=abc123def456&entry_id=entry_2" # Update scheduled time curl -X POST \ -H "X-API-Key: your_api_key_here" \ -d "scheduled=10:30" \ "https://stagemonitor.app/api/program/update.php?id=abc123def456&entry_id=entry_2"

JavaScript:

const PROJECT_ID = 'abc123def456'; const API_KEY = 'your_api_key_here'; // Update entry async function updateEntry(projectId, apiKey, entryId, updates) { const params = new URLSearchParams(updates); const response = await fetch( `https://stagemonitor.app/api/program/update.php?id=${projectId}&entry_id=${entryId}`, { method: 'POST', headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/x-www-form-urlencoded' }, body: params } ); return await response.json(); } // Usage examples await updateEntry(PROJECT_ID, API_KEY, 'entry_2', { name: 'Extended Keynote', countdown: '01:00:00' }); await updateEntry(PROJECT_ID, API_KEY, 'entry_3', { message: 'Remember to mention sponsors' });

Python:

import requests PROJECT_ID = "abc123def456" API_KEY = "your_api_key_here" # Update entry response = requests.post( "https://stagemonitor.app/api/program/update.php", params={"id": PROJECT_ID, "entry_id": "entry_2"}, headers={"X-API-Key": API_KEY}, data={ "name": "Extended Keynote", "countdown": "01:00:00" } ) print(response.json()) # Helper function def update_entry(project_id, api_key, entry_id, **updates): return requests.post( "https://stagemonitor.app/api/program/update.php", params={"id": project_id, "entry_id": entry_id}, headers={"X-API-Key": api_key}, data=updates ).json() # Usage update_entry(PROJECT_ID, API_KEY, "entry_3", message="Break time!", scheduled="11:00")

GET Complete Active Entry AUTH REQUIRED

Mark the current active program entry as completed and advance to the next entry.

URL
/api/program/complete.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Authentication

Requires API Key via X-API-Key header or api_key query parameter.

Response
{ "ok": true, "completedEntryId": "entry_1", "message": "Entry marked as completed" }
Examples

cURL:

# Complete current entry and advance to next curl -H "X-API-Key: your_api_key_here" \ "https://stagemonitor.app/api/program/complete.php?id=abc123def456"

JavaScript:

const PROJECT_ID = 'abc123def456'; const API_KEY = 'your_api_key_here'; // Complete current entry fetch(`https://stagemonitor.app/api/program/complete.php?id=${PROJECT_ID}`, { headers: { 'X-API-Key': API_KEY } }) .then(response => response.json()) .then(data => { console.log('Completed entry:', data.completedEntryId); }); // Helper function async function completeCurrentEntry(projectId, apiKey) { const response = await fetch( `https://stagemonitor.app/api/program/complete.php?id=${projectId}`, { headers: { 'X-API-Key': apiKey } } ); return await response.json(); }

Python:

import requests PROJECT_ID = "abc123def456" API_KEY = "your_api_key_here" # Complete current entry response = requests.get( "https://stagemonitor.app/api/program/complete.php", params={"id": PROJECT_ID}, headers={"X-API-Key": API_KEY} ) data = response.json() print(f"Completed: {data['completedEntryId']}")

POST Reorder Program AUTH REQUIRED

Update the order of program entries. Supports separate ordering for active and completed entries.

URL
/api/program/order.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID (query parameter)
Request Body (JSON)
{ "activeOrder": ["entry_2", "entry_3", "entry_4"], "completedOrder": ["entry_1"] }

Alternative format (legacy): {"order": ["entry_1", "entry_2", "entry_3"]}

Authentication

Requires API Key via X-API-Key header or api_key query parameter.

Response
{ "ok": true, "message": "Order updated" }
Examples

cURL:

# Reorder entries curl -X POST \ -H "X-API-Key: your_api_key_here" \ -H "Content-Type: application/json" \ -d '{"activeOrder": ["entry_3", "entry_2", "entry_4"], "completedOrder": ["entry_1"]}' \ "https://stagemonitor.app/api/program/order.php?id=abc123def456"

JavaScript:

const PROJECT_ID = 'abc123def456'; const API_KEY = 'your_api_key_here'; // Reorder program entries async function reorderProgram(projectId, apiKey, activeOrder, completedOrder = []) { const response = await fetch( `https://stagemonitor.app/api/program/order.php?id=${projectId}`, { method: 'POST', headers: { 'X-API-Key': apiKey, 'Content-Type': 'application/json' }, body: JSON.stringify({ activeOrder, completedOrder }) } ); return await response.json(); } // Usage - move entry_3 to the top await reorderProgram(PROJECT_ID, API_KEY, ['entry_3', 'entry_2', 'entry_4'], // active entries ['entry_1'] // completed entries );

Python:

import requests import json PROJECT_ID = "abc123def456" API_KEY = "your_api_key_here" # Reorder program entries response = requests.post( "https://stagemonitor.app/api/program/order.php", params={"id": PROJECT_ID}, headers={ "X-API-Key": API_KEY, "Content-Type": "application/json" }, json={ "activeOrder": ["entry_3", "entry_2", "entry_4"], "completedOrder": ["entry_1"] } ) print(response.json()) # Helper function def reorder_program(project_id, api_key, active_order, completed_order=None): payload = {"activeOrder": active_order} if completed_order: payload["completedOrder"] = completed_order return requests.post( "https://stagemonitor.app/api/program/order.php", params={"id": project_id}, headers={"X-API-Key": api_key, "Content-Type": "application/json"}, json=payload ).json()

Monitor API

Get real-time monitor data and connection information.

GET Get Monitor Data

Get comprehensive monitor display data including active entry, next entry, visibility settings, progress, and pause state.

URL
/api/monitor/data.php?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Response
{ "ok": true, "activeEntry": { "id": "entry_1", "name": "Opening Remarks", "message": "Welcome everyone!", "countdown": "00:15:00", "scheduled": "09:00" }, "nextEntry": { "id": "entry_2", "name": "Keynote Speech", "message": "", "countdown": "00:45:00", "scheduled": "09:15" }, "visibility": { "showCountdown": true, "showMessage": true, "showProgress": true, "showNext": true }, "progress": 0.25, "paused": false }
Examples

cURL:

# Get all monitor data curl "https://stagemonitor.app/api/monitor/data.php?id=abc123def456"

JavaScript:

// Get monitor data fetch('https://stagemonitor.app/api/monitor/data.php?id=abc123def456') .then(response => response.json()) .then(data => { console.log('Current:', data.activeEntry?.name); console.log('Next:', data.nextEntry?.name); console.log('Progress:', Math.round(data.progress * 100) + '%'); console.log('Paused:', data.paused); }); // Build custom monitor display async function getMonitorData(projectId) { const response = await fetch(`https://stagemonitor.app/api/monitor/data.php?id=${projectId}`); return await response.json(); } // Poll for updates setInterval(async () => { const data = await getMonitorData('abc123def456'); updateDisplay(data); }, 1000);

Python:

import requests import time PROJECT_ID = "abc123def456" # Get monitor data response = requests.get( "https://stagemonitor.app/api/monitor/data.php", params={"id": PROJECT_ID} ) data = response.json() print(f"Current: {data['activeEntry']['name'] if data.get('activeEntry') else 'None'}") print(f"Next: {data['nextEntry']['name'] if data.get('nextEntry') else 'None'}") print(f"Progress: {data['progress'] * 100:.0f}%") print(f"Paused: {data['paused']}") # Continuous monitoring def monitor_loop(project_id, interval=1): while True: data = requests.get( "https://stagemonitor.app/api/monitor/data.php", params={"id": project_id} ).json() # Process data... print(f"Progress: {data['progress'] * 100:.0f}%") time.sleep(interval)

GET Get Viewer Connections

Get the current number of connected viewers and the maximum allowed viewers.

URL
/api/connections/?id={PROJECT_ID}
Parameters
ParameterTypeRequiredDescription
idstringYesYour project ID
Response
{ "ok": true, "count": 5, "max": 100 }
Examples

cURL:

# Get connection count curl "https://stagemonitor.app/api/connections/?id=abc123def456"

JavaScript:

// Get viewer count fetch('https://stagemonitor.app/api/connections/?id=abc123def456') .then(response => response.json()) .then(data => { console.log(`Viewers: ${data.count}/${data.max}`); });

Python:

import requests PROJECT_ID = "abc123def456" response = requests.get( "https://stagemonitor.app/api/connections/", params={"id": PROJECT_ID} ) data = response.json() print(f"Viewers: {data['count']}/{data['max']}")

WebSocket API

For real-time updates, connect to our WebSocket server. This is more efficient than polling for applications that need instant updates.

Connection URL

wss://stagemonitor.app:8080

Subscribe to a Project

After connecting, send a subscribe message to start receiving updates.

{ "type": "subscribe", "projectId": "YOUR_PROJECT_ID", "role": "viewer" // or "admin" for sending updates }

Message Types

TypeDirectionDescription
subscribeClient → ServerSubscribe to a project's updates
updateServer → ClientBroadcast update (countdown, note, program changes)
pingClient → ServerKeep connection alive
pongServer → ClientResponse to ping

Complete Example

JavaScript:

const PROJECT_ID = 'abc123def456'; class StagemonitorClient { constructor(projectId, role = 'viewer') { this.projectId = projectId; this.role = role; this.ws = null; this.reconnectInterval = 5000; } connect() { this.ws = new WebSocket('wss://stagemonitor.app:8080'); this.ws.onopen = () => { console.log('Connected to Stagemonitor'); this.subscribe(); }; this.ws.onmessage = (event) => { const data = JSON.parse(event.data); this.handleMessage(data); }; this.ws.onclose = () => { console.log('Disconnected, reconnecting...'); setTimeout(() => this.connect(), this.reconnectInterval); }; this.ws.onerror = (error) => { console.error('WebSocket error:', error); }; } subscribe() { this.ws.send(JSON.stringify({ type: 'subscribe', projectId: this.projectId, role: this.role })); } handleMessage(data) { switch (data.type) { case 'update': console.log('Update received:', data.updateType, data.value); // Handle different update types if (data.updateType === 'countdown') { this.onCountdownUpdate(data.value); } else if (data.updateType === 'note') { this.onNoteUpdate(data.value); } else if (data.updateType === 'program') { this.onProgramUpdate(data.value); } break; case 'pong': // Connection alive break; } } onCountdownUpdate(value) { console.log('Countdown:', value); } onNoteUpdate(value) { console.log('Note:', value); } onProgramUpdate(value) { console.log('Program updated:', value); } // Keep connection alive startPing() { setInterval(() => { if (this.ws.readyState === WebSocket.OPEN) { this.ws.send(JSON.stringify({ type: 'ping' })); } }, 30000); } } // Usage const client = new StagemonitorClient(PROJECT_ID); client.connect(); client.startPing();

Python:

import asyncio import websockets import json PROJECT_ID = "abc123def456" async def connect_to_stagemonitor(): uri = "wss://stagemonitor.app:8080" async with websockets.connect(uri) as ws: # Subscribe to project await ws.send(json.dumps({ "type": "subscribe", "projectId": PROJECT_ID, "role": "viewer" })) print("Subscribed to project") # Listen for updates async for message in ws: data = json.loads(message) if data["type"] == "update": print(f"Update: {data['updateType']} = {data['value']}") elif data["type"] == "pong": pass # Connection alive # Run the client asyncio.run(connect_to_stagemonitor())

Integration Examples

Bitfocus Companion

Use the "Generic HTTP" module for simple triggers, or "Generic HTTP with Variables" for more control.

# Button for 5 minute countdown (public endpoint) https://stagemonitor.app/api/countdown/?id=YOUR_PROJECT_ID&hh=0&mm=5&ss=0 # Button for 10 minute countdown https://stagemonitor.app/api/countdown/?id=YOUR_PROJECT_ID&hh=0&mm=10&ss=0 # Toggle pause https://stagemonitor.app/api/countdown/pause.php?id=YOUR_PROJECT_ID # Set message "LIVE" https://stagemonitor.app/api/note/?id=YOUR_PROJECT_ID¬e=LIVE # Clear message https://stagemonitor.app/api/note/?id=YOUR_PROJECT_ID¬e= # Add 5 minutes (requires API key in header) URL: https://stagemonitor.app/api/countdown/add.php?id=YOUR_PROJECT_ID&min=5 Header: X-API-Key: YOUR_API_KEY # Complete current entry (requires API key) URL: https://stagemonitor.app/api/program/complete.php?id=YOUR_PROJECT_ID Header: X-API-Key: YOUR_API_KEY

Stream Deck (via Web Requests Plugin)

# Simple GET request buttons work for public endpoints # For authenticated endpoints, use the "HTTP Request" action with custom headers URL: https://stagemonitor.app/api/countdown/add.php?id=YOUR_PROJECT_ID&min=5 Method: GET Headers: X-API-Key: YOUR_API_KEY

Complete Python Automation Example

import requests import time class StagemonitorAPI: """Complete Stagemonitor API client""" def __init__(self, project_id, api_key=None): self.project_id = project_id self.api_key = api_key self.base_url = "https://stagemonitor.app/api" def _get(self, endpoint, params=None, auth_required=False): """Make a GET request""" if params is None: params = {} params["id"] = self.project_id headers = {} if auth_required and self.api_key: headers["X-API-Key"] = self.api_key response = requests.get(f"{self.base_url}/{endpoint}", params=params, headers=headers) return response def _post(self, endpoint, params=None, data=None, json_data=None): """Make a POST request (always authenticated)""" if params is None: params = {} params["id"] = self.project_id headers = {"X-API-Key": self.api_key} if self.api_key else {} if json_data: headers["Content-Type"] = "application/json" response = requests.post( f"{self.base_url}/{endpoint}", params=params, headers=headers, data=data, json=json_data ) return response # Countdown methods def set_countdown(self, hours, minutes, seconds): return self._get("countdown/", {"hh": hours, "mm": minutes, "ss": seconds}).json() def get_countdown(self): return self._get("countdown/get.php").text def add_time(self, minutes): return self._get("countdown/add.php", {"min": minutes}, auth_required=True).json() def toggle_pause(self): return self._get("countdown/pause.php").json() # Note methods def set_note(self, note): return self._get("note/", {"note": note}).json() def get_note(self): return self._get("note/get.php").text # Program methods def get_program(self): return self._get("program/get.php").json() def update_entry(self, entry_id, **updates): return self._post("program/update.php", {"entry_id": entry_id}, data=updates).json() def complete_entry(self): return self._get("program/complete.php", auth_required=True).json() def reorder_program(self, active_order, completed_order=None): data = {"activeOrder": active_order} if completed_order: data["completedOrder"] = completed_order return self._post("program/order.php", json_data=data).json() # Monitor methods def get_monitor_data(self): return self._get("monitor/data.php").json() def get_connections(self): return self._get("connections/").json() # Usage example if __name__ == "__main__": api = StagemonitorAPI( project_id="abc123def456", api_key="your_api_key_here" ) # Set 10 minute countdown api.set_countdown(0, 10, 0) # Set note api.set_note("Welcome!") # Get current status data = api.get_monitor_data() print(f"Current: {data['activeEntry']['name']}") print(f"Countdown: {api.get_countdown()}") # Add 5 minutes (requires API key) api.add_time(5) # Complete current entry (requires API key) api.complete_entry()

Rate Limits

There are no strict rate limits, but please be reasonable to ensure service quality for all users.

Recommended Limits
OperationRecommended Max Rate
Countdown/Note updates1 request per second
Polling (GET requests)1 request per second per client
Program operations1 request per second
Tip: For real-time updates, use the WebSocket API instead of polling. It's more efficient and provides instant updates.

Error Responses

All endpoints return appropriate HTTP status codes and JSON error messages.

HTTP CodeMeaningExample Response
400 Bad Request - Missing or invalid parameters {"error": "Missing required parameter: id"}
401 Unauthorized - Missing or invalid API key {"error": "Authentication required"}
403 Forbidden - Project has expired or API key invalid {"error": "Project expired"}
404 Not Found - Project or entry does not exist {"error": "Project not found"}
500 Server Error - Internal server error {"error": "Internal server error"}
Error Handling Example
// JavaScript async function safeApiCall(url, options = {}) { try { const response = await fetch(url, options); if (!response.ok) { const error = await response.json(); throw new Error(error.error || `HTTP ${response.status}`); } return await response.json(); } catch (error) { console.error('API Error:', error.message); throw error; } } // Python def safe_api_call(url, **kwargs): try: response = requests.get(url, **kwargs) response.raise_for_status() return response.json() except requests.exceptions.HTTPError as e: error_data = e.response.json() print(f"API Error: {error_data.get('error', str(e))}") raise

Quick Reference

EndpointMethodAuthDescription
/api/countdown/GETNoSet countdown timer
/api/countdown/get.phpGETNoGet countdown display value
/api/countdown/add.phpGETYesAdd/subtract time
/api/countdown/pause.phpGETNoToggle pause state
/api/note/GETNoSet note/message
/api/note/get.phpGETNoGet current note
/api/program/get.phpGETNoGet full program
/api/program/update.phpPOSTYesUpdate program entry
/api/program/complete.phpGETYesComplete active entry
/api/program/order.phpPOSTYesReorder program
/api/monitor/data.phpGETNoGet monitor data
/api/connections/GETNoGet viewer count

Need help? Contact us at stagemonitor@oclin.no