KUMA Timer — API Reference

HTTP/JSON API & OSC protocol for integration with Bitfocus Companion, show control systems, and custom automation

Overview

KUMA Timer exposes two integration protocols:

ProtocolUse caseDefault port
HTTP / JSONBitfocus Companion module, custom scripts, web dashboards5555
OSC / UDPLighting consoles, legacy show control, QLab8000 (in) · 12321 (out)
Recommendation: Use the HTTP API for new integrations. It provides full SMS control (colours, effects), live cue name, SMS active state, and progress percentage — none of which are available over OSC.

Both protocols are enabled and configured in Settings → Connections. The HTTP server runs on the same port as the Web Mirror (default 5555). No authentication is required — restrict access at network level if needed.


HTTP API

Base URL: http://<kuma-ip>:5555

All responses are application/json. CORS headers are set to * so browser-based dashboards can poll directly.

Status endpoint

GET /api/status Full timer state snapshot

Returns the current state of KUMA Timer. Companions polls this every 500 ms by default.

Response 200

{
  "status":        "live",       // "live" | "paused" | "standby" | "hidden"
  "timer":         "04:32",     // display string, "-MM:SS" in overtime
  "timer_seconds": 272,         // integer, negative in overtime
  "overtime":      false,       // true once timer passes zero
  "progress":      74.3,        // 100→0, matches progress bar
  "cue_name":      "Jan Kowalski",// empty string if no cue loaded
  "cue_index":     2,           // -1 if no cue selected
  "sms_active":    false        // true while a message is on screen
}

Command endpoint

POST /api/command Execute a timer action

Body: application/json with "action" plus optional parameters.
All commands are dispatched to the Qt main thread — safe to call from any thread or process.

Response 200  {"ok": true}

Response 400  {"error": "unknown action: foo"}


Actions reference

Playback

actionParametersDescription
"start"Start the timer
"pause"Toggle pause / resume
"reset"Stop and reset to zero
"hide"Toggle display window visibility

Time

actionParametersDescription
"add_minute" Add 60 seconds to the running timer
"sub_minute" Subtract 60 seconds from the running timer
"load_time" seconds int Load an exact duration in seconds (e.g. 300 = 5:00)
"preset" index int 0–5 Activate preset button by index (0 = first button in the row)

Cues

actionParametersDescription
"load_cue" index int Load a runsheet cue by index (0 = first row). Loads time and name.
"next_cue" Advance to the next cue in the runsheet (wraps to top)

SMS — Send Message to Screen

ParameterTypeDefaultDescription
textstringrequiredMessage to display (max 300 chars)
durationint10How long to show the message, in seconds (1–600)
colorstring"#ffffff"Text colour as hex (e.g. "#ff4444")
border_colorstring"#ffaa00"Container border colour as hex
sizestring"medium""small" · "medium" · "large"
positionstring"bottom""bottom" · "top"
flashboolfalseFlash the container on/off for attention
scrollboolfalseForce scrolling even if text fits on screen
scroll_invertboolfalseScroll right-to-left (Arabic / Hebrew)
Auto-scroll: If the message text is wider than the container it scrolls automatically, regardless of the scroll flag. The flag only forces scrolling for short messages too.
Dark text: When color is #000000 the container background switches to white automatically so the text is legible.

To remove a message early:

actionParametersDescription
"cancel_sms"Remove the current on-screen message immediately

OSC Protocol

KUMA listens for OSC/UDP on port 8000 (configurable in Settings → Connections). Useful for QLab, ETC Eos, MA consoles, and other show control systems.

Incoming — external device → KUMA

AddressArgumentAction
OSC /kuma/startStart timer
OSC /kuma/pausePause / resume toggle
OSC /kuma/resetStop and reset to zero
OSC /kuma/hideToggle display window visibility
OSC /kuma/time/add+1 minute
OSC /kuma/time/sub−1 minute
OSC /kuma/warpint secondsLoad duration in seconds (e.g. 300 = 5:00). Alias: /kuma/load
OSC /kuma/presetint 0–5Load preset by index (0 = first button)
OSC /kuma/cueint indexLoad cue from runsheet by index
OSC /kuma/cue/nextAdvance to next cue (wraps)
OSC /kuma/settimestringLoad time as HH:MM:SS or MM:SS (e.g. "01:30:00")
OSC /kuma/smsstring text · int durationSend message using config defaults for colour/size/position

Outgoing — KUMA → external

Default target: 127.0.0.1 : 12321 (configurable)

AddressValueSent when
/kuma/statusstring"LIVE" · "PAUSED" · "STANDBY" · "HIDDEN"On any state change
/kuma/overtimeint 1Once, when the timer first crosses zero. Path is configurable in Settings.
Note: The OSC /kuma/sms command uses the colour/size/position defaults set in Settings → SMS. For full per-message styling use the HTTP API.

Bitfocus Companion Module

The KUMA Timer Companion module is built on the HTTP API. It polls /api/status every 500 ms and sends all commands via POST /api/command.

CapabilityDetail
ActionsStart, Pause, Reset, Hide, ±1 min, Load Time, Preset, Load Cue, Next Cue, Send SMS (full styling), Cancel SMS
FeedbacksLIVE · PAUSED · STANDBY · HIDDEN · OVERTIME · SMS active
Variables$(kumatimer:timer) · $(kumatimer:timer_seconds) · $(kumatimer:status) · $(kumatimer:cue_name) · $(kumatimer:cue_index) · $(kumatimer:overtime) · $(kumatimer:progress) · $(kumatimer:sms_active)
ConfigKUMA IP · port (default 5555) · poll interval (default 500 ms)

Download from the Download page. Install as a developer module — see Documentation → Companion Module for step-by-step instructions.


Code examples

cURL — start the timer

curl -s -X POST http://192.168.1.10:5555/api/command \
  -H "Content-Type: application/json" \
  -d '{"action":"start"}'

cURL — send a red flashing SMS for 20 seconds

curl -s -X POST http://192.168.1.10:5555/api/command \
  -H "Content-Type: application/json" \
  -d '{
    "action":       "send_sms",
    "text":         "PLEASE WRAP UP",
    "duration":     20,
    "color":        "#ff4444",
    "border_color": "#ff0000",
    "size":         "large",
    "position":     "top",
    "flash":        true
  }'

cURL — load cue #3 and read status

# Load cue index 2 (third row)
curl -s -X POST http://192.168.1.10:5555/api/command \
  -H "Content-Type: application/json" \
  -d '{"action":"load_cue","index":2}'

# Poll current state
curl -s http://192.168.1.10:5555/api/status | python3 -m json.tool

Python — poll loop

import urllib.request, json, time

KUMA = "http://192.168.1.10:5555"

def command(action, **params):
    body = json.dumps({"action": action, **params}).encode()
    req  = urllib.request.Request(f"{KUMA}/api/command", body,
                                  {"Content-Type": "application/json"})
    urllib.request.urlopen(req)

def status():
    with urllib.request.urlopen(f"{KUMA}/api/status") as r:
        return json.loads(r.read())

command("load_time", seconds=300)
command("start")

while True:
    s = status()
    print(f"{s['timer']}  [{s['status'].upper()}]  cue: {s['cue_name'] or '—'}")
    if s["overtime"]:
        command("send_sms", text="OVERTIME!", duration=30,
                color="#ff4444", flash=True)
        break
    time.sleep(1)

Node.js — one-liner command

// npm i node-fetch   (or use native fetch in Node 18+)
await fetch("http://192.168.1.10:5555/api/command", {
  method:  "POST",
  headers: { "Content-Type": "application/json" },
  body:    JSON.stringify({ action: "next_cue" }),
})

QLab (OSC) — start on cue fire

// Network cue → UDP → 192.168.1.10:8000
/kuma/start