Run the show from anywhere.
A small, opinionated HTTP API for driving timers, sending messages, and triggering stage effects. Built for Bitfocus Companion, Stream Deck, and any automation that can make HTTP requests.
Bearer token in the Authorization header. Generate keys from /account/api.
https://ezstagemanager.com/api/v1 — same host as the app.
Request/response are JSON. Many endpoints also accept URL query params for easier Companion setup.
Five-minute setup.
- Make sure you're on Pro. API access is Pro-only.
- Generate a key at /account/api. Copy the full key — you'll only see it once.
- Identify the room code you want to drive (e.g.,
abc-1234). - Send a request.
curl -X POST https://ezstagemanager.com/api/v1/rooms/abc-1234/timer/start \ -H "Authorization: Bearer ezsm_live_..."
Open the controller and viewer in browser tabs while you test — every request reflects immediately via realtime sync.
One header. One key. That's it.
Every request must include an Authorization header with a Bearer token:
Authorization: Bearer ezsm_live_a3kf9c2...
- Keys are scoped to your user account, not individual rooms.
- A key only works on rooms you own.
- Keys are validated against your active Pro subscription on every request — if your sub lapses, your keys stop working.
- Revoking a key in
/account/apikills it immediately. - The full key is shown once at creation. If you lose it, revoke and create a new one.
The full surface.
All paths are relative to https://ezstagemanager.com/api/v1. Replace {code} with your room code (theabc-1234 in your URL).
/rooms/{code}/timer/startStart the timer.
Begins or resumes the countdown from the current paused-remaining value (or full duration if never started).
curl -X POST https://ezstagemanager.com/api/v1/rooms/abc-1234/timer/start \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true }/rooms/{code}/timer/pausePause and capture remaining seconds.
Captures the current remaining time (including negative overtime) and pauses. The next /start resumes from this value.
curl -X POST https://ezstagemanager.com/api/v1/rooms/abc-1234/timer/pause \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true, "remaining_seconds": 224 }/rooms/{code}/timer/resetReset to the full duration.
Stops the timer and restores paused_remaining_seconds to the room's full duration.
curl -X POST https://ezstagemanager.com/api/v1/rooms/abc-1234/timer/reset \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true }/rooms/{code}/timer/addAdd or subtract time.
Use ?seconds=60 (or JSON body { seconds: 60 }). Negative values subtract.
# Add a minute curl -X POST "https://ezstagemanager.com/api/v1/rooms/abc-1234/timer/add?seconds=60" \ -H "Authorization: Bearer ezsm_live_..." # Subtract 30 seconds curl -X POST "https://ezstagemanager.com/api/v1/rooms/abc-1234/timer/add?seconds=-30" \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true, "added_seconds": 60 }/rooms/{code}/messageSend a message to stage.
Body { text, type } or ?text=...&type=... query params. type is one of "info", "warning", "alert" (default: info).
curl -X POST "https://ezstagemanager.com/api/v1/rooms/abc-1234/message?text=Wrap+up&type=warning" \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true, "text": "Wrap up", "type": "warning" }/rooms/{code}/messageClear the active stage message.
Removes any message currently shown on the viewer.
curl -X DELETE https://ezstagemanager.com/api/v1/rooms/abc-1234/message \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true }/rooms/{code}/blackoutSet or toggle blackout.
Pass ?state=on or ?state=off to set explicitly. Omit the param to toggle the current state.
# Toggle curl -X POST https://ezstagemanager.com/api/v1/rooms/abc-1234/blackout \ -H "Authorization: Bearer ezsm_live_..." # Force on curl -X POST "https://ezstagemanager.com/api/v1/rooms/abc-1234/blackout?state=on" \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true, "is_blackout": true }/rooms/{code}/flashFlash the stage screen white.
Triggers a brief white flash on all connected viewers — useful for grabbing a speaker's attention.
curl -X POST https://ezstagemanager.com/api/v1/rooms/abc-1234/flash \ -H "Authorization: Bearer ezsm_live_..."
{ "ok": true }/rooms/{code}Read current room state.
Useful for Companion feedback — show live remaining time on a button face.
curl https://ezstagemanager.com/api/v1/rooms/abc-1234 \ -H "Authorization: Bearer ezsm_live_..."
{
"code": "abc-1234",
"duration_seconds": 300,
"remaining_seconds": 224,
"is_running": true,
"is_blackout": false
}Status codes.
200OK —Request succeeded.
400Bad Request —Missing or invalid parameters — e.g., no text on a message endpoint.
401Unauthorized —Missing Authorization header, or key is invalid/revoked.
403Forbidden —Key is valid but your subscription isn't active, or the room isn't yours.
404Not Found —Room code doesn't exist.
500Server Error —Something broke on our side — try again, then file a bug if it persists.
Error responses always include a JSON body with an error field describing the problem.
Physical buttons in 10 minutes.
- Download Bitfocus Companion — it's free, works without a physical Stream Deck (use the on-screen Emulator surface).
- In Companion, go to Connections → Add connection → search for and add the Generic HTTP module.
- Go to Buttons → click any empty slot → Add action → pick HTTP POST from the Generic HTTP module.
- In the action's URL field, paste:
https://ezstagemanager.com/api/v1/rooms/YOUR_ROOM/timer/start. - Under the action's Headers, click Add header. Name =
Authorization, Value =Bearer YOUR_KEY. - Press the button (physical or emulator). Your timer starts.
Repeat for each action you want a button for — pause, reset, +1 min, flash, etc. For per-segment messages, set the URL to .../message?text=Wrap+up&type=warning with no body needed.
No hard limits, just don’t be weird.
The API has no enforced rate limit right now. We trust you to use it reasonably — one request per button press, not 10/second on a polling loop. If you have a high-volume integration in mind, email support@ezstagemanager.com first and we’ll work it out.
For state-reading needs, prefer the realtime websocket connection in the viewer page over polling the GET endpoint — same data, zero latency, zero load on us.