API Documentation
Use the Stagemonitor API to control your monitors programmatically.
Authentication
Stagemonitor uses two types of identifiers:
| Identifier | Purpose | Where 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
| Parameter | Type | Required | Description |
id | string | Yes | Your project ID |
hh | integer | Yes | Hours (0-99) |
mm | integer | Yes | Minutes (0-59) |
ss | integer | Yes | Seconds (0-59) |
redir | boolean | No | Set 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your project ID |
min | integer | Yes | Minutes to add (negative to subtract) |
redir | boolean | No | Set 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your project ID |
note | string | Yes | The 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your project ID (query parameter) |
entry_id | string | Yes | The entry ID to update (query parameter) |
Request Body (form data)
| Field | Type | Required | Description |
name | string | No | Entry name/title |
message | string | No | Note/message for this entry |
countdown | string | No | Countdown duration (HH:MM:SS format) |
scheduled | string | No | Scheduled 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Parameter | Type | Required | Description |
id | string | Yes | Your 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
| Type | Direction | Description |
subscribe | Client → Server | Subscribe to a project's updates |
update | Server → Client | Broadcast update (countdown, note, program changes) |
ping | Client → Server | Keep connection alive |
pong | Server → Client | Response 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
| Operation | Recommended Max Rate |
| Countdown/Note updates | 1 request per second |
| Polling (GET requests) | 1 request per second per client |
| Program operations | 1 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 Code | Meaning | Example 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
| Endpoint | Method | Auth | Description |
/api/countdown/ | GET | No | Set countdown timer |
/api/countdown/get.php | GET | No | Get countdown display value |
/api/countdown/add.php | GET | Yes | Add/subtract time |
/api/countdown/pause.php | GET | No | Toggle pause state |
/api/note/ | GET | No | Set note/message |
/api/note/get.php | GET | No | Get current note |
/api/program/get.php | GET | No | Get full program |
/api/program/update.php | POST | Yes | Update program entry |
/api/program/complete.php | GET | Yes | Complete active entry |
/api/program/order.php | POST | Yes | Reorder program |
/api/monitor/data.php | GET | No | Get monitor data |
/api/connections/ | GET | No | Get viewer count |
Need help? Contact us at stagemonitor@oclin.no